From 1182a99d041e3461b5493f2f800a434f41a9eee1 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Sun, 13 Apr 2025 06:55:22 +0000 Subject: [PATCH 01/22] [AMF/MME] Fix potential buffer overflow in ASCII-to-USC2 conversion In amf_context_parse_config(), update the loop condition to ensure that ((i * 2) + 1) remains below (OGS_NAS_MAX_NETWORK_NAME_LEN - 1) before performing any writes. This change prevents potential out-of-bounds memory writes during the conversion of an ASCII string to USC-2, thereby fixing a buffer overflow issue. This issue was observed on Ubuntu 25.04 and reported in the osmocom nightly package. --- src/amf/context.c | 20 ++++++++++++-------- src/mme/mme-context.c | 20 ++++++++++++-------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/amf/context.c b/src/amf/context.c index 69e90fd20..67a0ae685 100644 --- a/src/amf/context.c +++ b/src/amf/context.c @@ -977,12 +977,14 @@ int amf_context_parse_config(void) ogs_yaml_iter_value(&network_name_iter); uint8_t size = strlen(c_network_name); uint8_t i; - for (i = 0;iname[i*2] = 0; - network_full_name->name[(i*2)+1] = + network_full_name->name[i * 2] = 0; + network_full_name->name[i * 2 + 1] = c_network_name[i]; - } network_full_name->length = size*2+1; network_full_name->coding_scheme = 1; @@ -994,12 +996,14 @@ int amf_context_parse_config(void) ogs_yaml_iter_value(&network_name_iter); uint8_t size = strlen(c_network_name); uint8_t i; - for (i = 0;iname[i*2] = 0; - network_short_name->name[(i*2)+1] = + network_short_name->name[i * 2] = 0; + network_short_name->name[i * 2 + 1] = c_network_name[i]; - } network_short_name->length = size*2+1; network_short_name->coding_scheme = 1; diff --git a/src/mme/mme-context.c b/src/mme/mme-context.c index 46de8485a..ca26836d2 100644 --- a/src/mme/mme-context.c +++ b/src/mme/mme-context.c @@ -2014,12 +2014,14 @@ int mme_context_parse_config(void) ogs_yaml_iter_value(&network_name_iter); uint8_t size = strlen(c_network_name); uint8_t i; - for (i = 0;iname[i*2] = 0; - network_full_name->name[(i*2)+1] = + network_full_name->name[i * 2] = 0; + network_full_name->name[i * 2 + 1] = c_network_name[i]; - } network_full_name->length = size*2+1; network_full_name->coding_scheme = 1; @@ -2031,12 +2033,14 @@ int mme_context_parse_config(void) ogs_yaml_iter_value(&network_name_iter); uint8_t size = strlen(c_network_name); uint8_t i; - for (i = 0;iname[i*2] = 0; - network_short_name->name[(i*2)+1] = + network_short_name->name[i * 2] = 0; + network_short_name->name[i * 2 + 1] = c_network_name[i]; - } network_short_name->length = size*2+1; network_short_name->coding_scheme = 1; From 726b588d76bc492194c8f7444976fd4294af7b15 Mon Sep 17 00:00:00 2001 From: shellwayxw Date: Wed, 9 Apr 2025 01:02:03 -0400 Subject: [PATCH 02/22] Fix integer overflow in PFCP ogs_pfcp_parse_sdf_filter() --- lib/pfcp/types.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pfcp/types.c b/lib/pfcp/types.c index 3538acf6c..9d1ddf298 100644 --- a/lib/pfcp/types.c +++ b/lib/pfcp/types.c @@ -304,7 +304,7 @@ int16_t ogs_pfcp_build_sdf_filter( int16_t ogs_pfcp_parse_sdf_filter( ogs_pfcp_sdf_filter_t *filter, ogs_tlv_octet_t *octet) { - int16_t size = 0; + uint32_t size = 0; ogs_assert(filter); ogs_assert(octet); From 31d3f575d243e8ae7d4ae5211f326aa8d51cb02d Mon Sep 17 00:00:00 2001 From: shellwayxw Date: Wed, 9 Apr 2025 01:13:01 -0400 Subject: [PATCH 03/22] Fix stack overflow in ogs_pfcp_extract_node_id() --- lib/pfcp/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pfcp/util.c b/lib/pfcp/util.c index 295f1211c..cb273a207 100644 --- a/lib/pfcp/util.c +++ b/lib/pfcp/util.c @@ -194,7 +194,7 @@ ogs_pfcp_extract_node_id(ogs_pfcp_message_t *message, goto done; } - memcpy(node_id, tlv_node_id->data, tlv_node_id->len); + memcpy(node_id, tlv_node_id->data, ogs_min(tlv_node_id->len, sizeof(ogs_pfcp_node_id_t))); if (node_id->type != OGS_PFCP_NODE_ID_IPV4 && node_id->type != OGS_PFCP_NODE_ID_IPV6 && From 90cb00ced3450bf875ff4f5e55906fc8ba921a06 Mon Sep 17 00:00:00 2001 From: shellwayxw Date: Wed, 9 Apr 2025 11:41:24 -0400 Subject: [PATCH 04/22] Always make fqdn a NULL terminated string --- lib/pfcp/util.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/pfcp/util.c b/lib/pfcp/util.c index cb273a207..2c8e27bf9 100644 --- a/lib/pfcp/util.c +++ b/lib/pfcp/util.c @@ -195,6 +195,7 @@ ogs_pfcp_extract_node_id(ogs_pfcp_message_t *message, } memcpy(node_id, tlv_node_id->data, ogs_min(tlv_node_id->len, sizeof(ogs_pfcp_node_id_t))); + node_id->fqdn[OGS_MAX_FQDN_LEN - 1] = '\0'; if (node_id->type != OGS_PFCP_NODE_ID_IPV4 && node_id->type != OGS_PFCP_NODE_ID_IPV6 && From cd80aa432e3593d5d4eaba9b8d6ad3ee851e9c19 Mon Sep 17 00:00:00 2001 From: Pallavi Das Date: Thu, 17 Apr 2025 22:42:28 +0530 Subject: [PATCH 05/22] Typos Fix --- docs/_docs/tutorial/05-roaming.md | 2 +- lib/diameter/s6a/message.h | 2 +- src/amf/init.c | 4 ++-- src/ausf/init.c | 4 ++-- src/bsf/init.c | 4 ++-- src/hss/hss-context.c | 2 +- src/hss/hss-cx-path.c | 8 ++++---- src/hss/hss-init.c | 2 +- src/hss/hss-s6a-path.c | 2 +- src/hss/hss-swx-path.c | 2 +- src/mme/mme-init.c | 2 +- src/mme/mme-s6a-handler.c | 2 +- src/nrf/init.c | 2 +- src/nssf/init.c | 4 ++-- src/pcf/init.c | 4 ++-- src/pcrf/pcrf-init.c | 2 +- src/scp/init.c | 4 ++-- src/sepp/app.c | 2 +- src/sepp/init.c | 4 ++-- src/sgwc/init.c | 2 +- src/sgwu/init.c | 2 +- src/smf/init.c | 4 ++-- src/udm/init.c | 4 ++-- src/udr/init.c | 4 ++-- src/upf/init.c | 2 +- tests/af/init.c | 4 ++-- 26 files changed, 40 insertions(+), 40 deletions(-) diff --git a/docs/_docs/tutorial/05-roaming.md b/docs/_docs/tutorial/05-roaming.md index e9f0b3a69..d7ebdcf44 100644 --- a/docs/_docs/tutorial/05-roaming.md +++ b/docs/_docs/tutorial/05-roaming.md @@ -354,7 +354,7 @@ $ ./install/bin/open5gs-udrd $ ./install/bin/open5gs-seppd -c ./install/etc/open5gs/sepp1.yaml ``` -#### Visted Network +#### Visited Network ``` $ ./install/bin/open5gs-nrfd $ ./install/bin/open5gs-scpd diff --git a/lib/diameter/s6a/message.h b/lib/diameter/s6a/message.h index f7322c1d8..35ad8a4e1 100644 --- a/lib/diameter/s6a/message.h +++ b/lib/diameter/s6a/message.h @@ -71,7 +71,7 @@ extern "C" { #define OGS_DIAM_S6A_CT_MME_UPDATE_PROCEDURE (0) #define OGS_DIAM_S6A_CT_SGSN_UPDATE_PROCEDURE (1) -#define OGS_DIAM_S6A_CT_SUBSCRIPTION_WITHDRAWL (2) +#define OGS_DIAM_S6A_CT_SUBSCRIPTION_WITHDRAWAL (2) #define OGS_DIAM_S6A_CT_UPDATE_PROCEDURE_IWF (3) #define OGS_DIAM_S6A_CT_INITIAL_ATTACH_PROCEDURE (4) diff --git a/src/amf/init.c b/src/amf/init.c index 2c5667488..864c21519 100644 --- a/src/amf/init.c +++ b/src/amf/init.c @@ -76,7 +76,7 @@ static void event_termination(void) { ogs_sbi_nf_instance_t *nf_instance = NULL; - /* Sending NF Instance De-registeration to NRF */ + /* Sending NF Instance De-registration to NRF */ ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance) ogs_sbi_nf_fsm_fini(nf_instance); @@ -128,7 +128,7 @@ static void amf_main(void *data) /* * After ogs_pollset_poll(), ogs_timer_mgr_expire() must be called. * - * The reason is why ogs_timer_mgr_next() can get the corrent value + * The reason is why ogs_timer_mgr_next() can get the current value * when ogs_timer_stop() is called internally in ogs_timer_mgr_expire(). * * You should not use event-queue before ogs_timer_mgr_expire(). diff --git a/src/ausf/init.c b/src/ausf/init.c index f8ce8eea5..7afc153ac 100644 --- a/src/ausf/init.c +++ b/src/ausf/init.c @@ -61,7 +61,7 @@ static void event_termination(void) { ogs_sbi_nf_instance_t *nf_instance = NULL; - /* Sending NF Instance De-registeration to NRF */ + /* Sending NF Instance De-registration to NRF */ ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance) ogs_sbi_nf_fsm_fini(nf_instance); @@ -108,7 +108,7 @@ static void ausf_main(void *data) /* * After ogs_pollset_poll(), ogs_timer_mgr_expire() must be called. * - * The reason is why ogs_timer_mgr_next() can get the corrent value + * The reason is why ogs_timer_mgr_next() can get the current value * when ogs_timer_stop() is called internally in ogs_timer_mgr_expire(). * * You should not use event-queue before ogs_timer_mgr_expire(). diff --git a/src/bsf/init.c b/src/bsf/init.c index ea9394947..bb67959ee 100644 --- a/src/bsf/init.c +++ b/src/bsf/init.c @@ -63,7 +63,7 @@ static void event_termination(void) { ogs_sbi_nf_instance_t *nf_instance = NULL; - /* Sending NF Instance De-registeration to NRF */ + /* Sending NF Instance De-registration to NRF */ ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance) ogs_sbi_nf_fsm_fini(nf_instance); @@ -111,7 +111,7 @@ static void bsf_main(void *data) /* * After ogs_pollset_poll(), ogs_timer_mgr_expire() must be called. * - * The reason is why ogs_timer_mgr_next() can get the corrent value + * The reason is why ogs_timer_mgr_next() can get the current value * when ogs_timer_stop() is called internally in ogs_timer_mgr_expire(). * * You should not use event-queue before ogs_timer_mgr_expire(). diff --git a/src/hss/hss-context.c b/src/hss/hss-context.c index 918fa4820..d62f640a9 100644 --- a/src/hss/hss-context.c +++ b/src/hss/hss-context.c @@ -1531,7 +1531,7 @@ int hss_handle_change_event(const bson_t *document) if (send_clr_flag) { ogs_info("[%s] Cancel Location Requested", imsi_bcd); hss_s6a_send_clr(imsi_bcd, NULL, NULL, - OGS_DIAM_S6A_CT_SUBSCRIPTION_WITHDRAWL); + OGS_DIAM_S6A_CT_SUBSCRIPTION_WITHDRAWAL); } else if (send_idr_flag) { ogs_info("[%s] Subscription-Data Changed", imsi_bcd); hss_s6a_send_idr(imsi_bcd, 0, subdatamask); diff --git a/src/hss/hss-cx-path.c b/src/hss/hss-cx-path.c index 18dbdc60e..37b4275bf 100644 --- a/src/hss/hss-cx-path.c +++ b/src/hss/hss-cx-path.c @@ -301,7 +301,7 @@ static int hss_ogs_diam_cx_mar_cb( struct msg **msg, struct avp *avp, /* 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", + ogs_error("User-Name[%s] Public-Identity[%s] is not associated", user_name, public_identity); result_code = OGS_DIAM_CX_ERROR_IDENTITIES_DONT_MATCH; goto out; @@ -545,7 +545,7 @@ static int hss_ogs_diam_cx_mar_cb( struct msg **msg, struct avp *avp, ret = fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD, avpch); ogs_assert(ret == 0); - /* Set the Integirty-Key AVP */ + /* Set the Integrity-Key AVP */ ret = fd_msg_avp_new(ogs_diam_cx_integrity_key, 0, &avpch); ogs_assert(ret == 0); val.os.data = ik; @@ -686,7 +686,7 @@ static int hss_ogs_diam_cx_sar_cb( struct msg **msg, struct avp *avp, /* 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", + ogs_error("User-Name[%s] Public-Identity[%s] is not associated", user_name, public_identity); result_code = OGS_DIAM_CX_ERROR_IDENTITIES_DONT_MATCH; goto out; @@ -717,7 +717,7 @@ static int hss_ogs_diam_cx_sar_cb( struct msg **msg, struct avp *avp, visited_network_identifier = hss_cx_get_visited_network_identifier(public_identity); if (!visited_network_identifier) { - ogs_error("Cannot find Visted-Network-Identifier " + ogs_error("Cannot find Visited-Network-Identifier " "for User-Name[%s] Public-Identity[%s]", user_name, public_identity); result_code = OGS_DIAM_CX_ERROR_IDENTITY_NOT_REGISTERED; diff --git a/src/hss/hss-init.c b/src/hss/hss-init.c index 288a2c537..6d5fb9892 100644 --- a/src/hss/hss-init.c +++ b/src/hss/hss-init.c @@ -99,7 +99,7 @@ static void hss_main(void *data) /* * After ogs_pollset_poll(), ogs_timer_mgr_expire() must be called. * - * The reason is why ogs_timer_mgr_next() can get the corrent value + * The reason is why ogs_timer_mgr_next() can get the current value * when ogs_timer_stop() is called internally in ogs_timer_mgr_expire(). * * You should not use event-queue before ogs_timer_mgr_expire(). diff --git a/src/hss/hss-s6a-path.c b/src/hss/hss-s6a-path.c index a055c9a9c..4b0481b84 100644 --- a/src/hss/hss-s6a-path.c +++ b/src/hss/hss-s6a-path.c @@ -1340,7 +1340,7 @@ void hss_s6a_send_clr(char *imsi_bcd, char *mme_host, char *mme_realm, /* Set the CLR-Flags */ ret = fd_msg_avp_new(ogs_diam_s6a_clr_flags, 0, &avp); ogs_assert(ret == 0); - if (cancellation_type == OGS_DIAM_S6A_CT_SUBSCRIPTION_WITHDRAWL) { + if (cancellation_type == OGS_DIAM_S6A_CT_SUBSCRIPTION_WITHDRAWAL) { val.u32 = (OGS_DIAM_S6A_CLR_FLAGS_REATTACH_REQUIRED | OGS_DIAM_S6A_CLR_FLAGS_S6A_S6D_INDICATOR); } else { diff --git a/src/hss/hss-swx-path.c b/src/hss/hss-swx-path.c index d9490e32a..881d6a10a 100644 --- a/src/hss/hss-swx-path.c +++ b/src/hss/hss-swx-path.c @@ -317,7 +317,7 @@ static int hss_ogs_diam_swx_mar_cb( struct msg **msg, struct avp *avp, ret = fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD, avpch); ogs_assert(ret == 0); - /* Set the Integirty-Key AVP */ + /* Set the Integrity-Key AVP */ ret = fd_msg_avp_new(ogs_diam_cx_integrity_key, 0, &avpch); ogs_assert(ret == 0); val.os.data = ik; diff --git a/src/mme/mme-init.c b/src/mme/mme-init.c index 7ceaa1d30..252456c67 100644 --- a/src/mme/mme-init.c +++ b/src/mme/mme-init.c @@ -126,7 +126,7 @@ static void mme_main(void *data) /* * After ogs_pollset_poll(), ogs_timer_mgr_expire() must be called. * - * The reason is why ogs_timer_mgr_next() can get the corrent value + * The reason is why ogs_timer_mgr_next() can get the current value * when ogs_timer_stop() is called internally in ogs_timer_mgr_expire(). * * You should not use event-queue before ogs_timer_mgr_expire(). diff --git a/src/mme/mme-s6a-handler.c b/src/mme/mme-s6a-handler.c index 0f759b970..75d44a310 100644 --- a/src/mme/mme-s6a-handler.c +++ b/src/mme/mme-s6a-handler.c @@ -277,7 +277,7 @@ void mme_s6a_handle_clr(mme_ue_t *mme_ue, ogs_diam_s6a_message_t *s6a_message) ogs_debug(" OGS_NAS_EPS TYPE[%d]", mme_ue->nas_eps.type); switch (clr_message->cancellation_type) { - case OGS_DIAM_S6A_CT_SUBSCRIPTION_WITHDRAWL: + case OGS_DIAM_S6A_CT_SUBSCRIPTION_WITHDRAWAL: mme_ue->detach_type = MME_DETACH_TYPE_HSS_EXPLICIT; /* diff --git a/src/nrf/init.c b/src/nrf/init.c index ef350294e..07042104c 100644 --- a/src/nrf/init.c +++ b/src/nrf/init.c @@ -102,7 +102,7 @@ static void nrf_main(void *data) /* * After ogs_pollset_poll(), ogs_timer_mgr_expire() must be called. * - * The reason is why ogs_timer_mgr_next() can get the corrent value + * The reason is why ogs_timer_mgr_next() can get the current value * when ogs_timer_stop() is called internally in ogs_timer_mgr_expire(). * * You should not use event-queue before ogs_timer_mgr_expire(). diff --git a/src/nssf/init.c b/src/nssf/init.c index c4c92a9b4..346e79d57 100644 --- a/src/nssf/init.c +++ b/src/nssf/init.c @@ -61,7 +61,7 @@ static void event_termination(void) { ogs_sbi_nf_instance_t *nf_instance = NULL; - /* Sending NF Instance De-registeration to NRF */ + /* Sending NF Instance De-registration to NRF */ ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance) ogs_sbi_nf_fsm_fini(nf_instance); @@ -108,7 +108,7 @@ static void nssf_main(void *data) /* * After ogs_pollset_poll(), ogs_timer_mgr_expire() must be called. * - * The reason is why ogs_timer_mgr_next() can get the corrent value + * The reason is why ogs_timer_mgr_next() can get the current value * when ogs_timer_stop() is called internally in ogs_timer_mgr_expire(). * * You should not use event-queue before ogs_timer_mgr_expire(). diff --git a/src/pcf/init.c b/src/pcf/init.c index cd1248319..7dc6d6544 100644 --- a/src/pcf/init.c +++ b/src/pcf/init.c @@ -74,7 +74,7 @@ static void event_termination(void) { ogs_sbi_nf_instance_t *nf_instance = NULL; - /* Sending NF Instance De-registeration to NRF */ + /* Sending NF Instance De-registration to NRF */ ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance) ogs_sbi_nf_fsm_fini(nf_instance); @@ -129,7 +129,7 @@ static void pcf_main(void *data) /* * After ogs_pollset_poll(), ogs_timer_mgr_expire() must be called. * - * The reason is why ogs_timer_mgr_next() can get the corrent value + * The reason is why ogs_timer_mgr_next() can get the current value * when ogs_timer_stop() is called internally in ogs_timer_mgr_expire(). * * You should not use event-queue before ogs_timer_mgr_expire(). diff --git a/src/pcrf/pcrf-init.c b/src/pcrf/pcrf-init.c index 925d31efd..f8e71aed2 100644 --- a/src/pcrf/pcrf-init.c +++ b/src/pcrf/pcrf-init.c @@ -103,7 +103,7 @@ static void pcrf_main(void *data) /* * After ogs_pollset_poll(), ogs_timer_mgr_expire() must be called. * - * The reason is why ogs_timer_mgr_next() can get the corrent value + * The reason is why ogs_timer_mgr_next() can get the current value * when ogs_timer_stop() is called internally in ogs_timer_mgr_expire(). * * You should not use event-queue before ogs_timer_mgr_expire(). diff --git a/src/scp/init.c b/src/scp/init.c index 400dece19..3e0c45ffb 100644 --- a/src/scp/init.c +++ b/src/scp/init.c @@ -63,7 +63,7 @@ static void event_termination(void) { ogs_sbi_nf_instance_t *nf_instance = NULL; - /* Sending NF Instance De-registeration to NRF */ + /* Sending NF Instance De-registration to NRF */ ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance) ogs_sbi_nf_fsm_fini(nf_instance); @@ -110,7 +110,7 @@ static void scp_main(void *data) /* * After ogs_pollset_poll(), ogs_timer_mgr_expire() must be called. * - * The reason is why ogs_timer_mgr_next() can get the corrent value + * The reason is why ogs_timer_mgr_next() can get the current value * when ogs_timer_stop() is called internally in ogs_timer_mgr_expire(). * * You should not use event-queue before ogs_timer_mgr_expire(). diff --git a/src/sepp/app.c b/src/sepp/app.c index 73d44f305..a1fc68948 100644 --- a/src/sepp/app.c +++ b/src/sepp/app.c @@ -25,7 +25,7 @@ int app_initialize(const char *const argv[]) rv = sepp_initialize(); if (rv != OGS_OK) { - ogs_error("Failed to intialize SEPP"); + ogs_error("Failed to initialize SEPP"); return rv; } ogs_info("SEPP initialize...done"); diff --git a/src/sepp/init.c b/src/sepp/init.c index 5dd97753a..78264813c 100644 --- a/src/sepp/init.c +++ b/src/sepp/init.c @@ -64,7 +64,7 @@ static void event_termination(void) ogs_sbi_nf_instance_t *nf_instance = NULL; sepp_node_t *sepp_node = NULL; - /* Sending NF Instance De-registeration to NRF */ + /* Sending NF Instance De-registration to NRF */ ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance) ogs_sbi_nf_fsm_fini(nf_instance); @@ -115,7 +115,7 @@ static void sepp_main(void *data) /* * After ogs_pollset_poll(), ogs_timer_mgr_expire() must be called. * - * The reason is why ogs_timer_mgr_next() can get the corrent value + * The reason is why ogs_timer_mgr_next() can get the current value * when ogs_timer_stop() is called internally in ogs_timer_mgr_expire(). * * You should not use event-queue before ogs_timer_mgr_expire(). diff --git a/src/sgwc/init.c b/src/sgwc/init.c index 92dd9945f..547f2ba5c 100644 --- a/src/sgwc/init.c +++ b/src/sgwc/init.c @@ -110,7 +110,7 @@ static void sgwc_main(void *data) /* * After ogs_pollset_poll(), ogs_timer_mgr_expire() must be called. * - * The reason is why ogs_timer_mgr_next() can get the corrent value + * The reason is why ogs_timer_mgr_next() can get the current value * when ogs_timer_stop() is called internally in ogs_timer_mgr_expire(). * * You should not use event-queue before ogs_timer_mgr_expire(). diff --git a/src/sgwu/init.c b/src/sgwu/init.c index 858e7ce07..f13e8781a 100644 --- a/src/sgwu/init.c +++ b/src/sgwu/init.c @@ -107,7 +107,7 @@ static void sgwu_main(void *data) /* * After ogs_pollset_poll(), ogs_timer_mgr_expire() must be called. * - * The reason is why ogs_timer_mgr_next() can get the corrent value + * The reason is why ogs_timer_mgr_next() can get the current value * when ogs_timer_stop() is called internally in ogs_timer_mgr_expire(). * * You should not use event-queue before ogs_timer_mgr_expire(). diff --git a/src/smf/init.c b/src/smf/init.c index 7de506cc0..83b7a4f41 100644 --- a/src/smf/init.c +++ b/src/smf/init.c @@ -101,7 +101,7 @@ static void event_termination(void) { ogs_sbi_nf_instance_t *nf_instance = NULL; - /* Sending NF Instance De-registeration to NRF */ + /* Sending NF Instance De-registration to NRF */ ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance) ogs_sbi_nf_fsm_fini(nf_instance); @@ -162,7 +162,7 @@ static void smf_main(void *data) /* * After ogs_pollset_poll(), ogs_timer_mgr_expire() must be called. * - * The reason is why ogs_timer_mgr_next() can get the corrent value + * The reason is why ogs_timer_mgr_next() can get the current value * when ogs_timer_stop() is called internally in ogs_timer_mgr_expire(). * * You should not use event-queue before ogs_timer_mgr_expire(). diff --git a/src/udm/init.c b/src/udm/init.c index 1842e5a93..36013d0fa 100644 --- a/src/udm/init.c +++ b/src/udm/init.c @@ -61,7 +61,7 @@ static void event_termination(void) { ogs_sbi_nf_instance_t *nf_instance = NULL; - /* Sending NF Instance De-registeration to NRF */ + /* Sending NF Instance De-registration to NRF */ ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance) ogs_sbi_nf_fsm_fini(nf_instance); @@ -108,7 +108,7 @@ static void udm_main(void *data) /* * After ogs_pollset_poll(), ogs_timer_mgr_expire() must be called. * - * The reason is why ogs_timer_mgr_next() can get the corrent value + * The reason is why ogs_timer_mgr_next() can get the current value * when ogs_timer_stop() is called internally in ogs_timer_mgr_expire(). * * You should not use event-queue before ogs_timer_mgr_expire(). diff --git a/src/udr/init.c b/src/udr/init.c index 87d1f9622..72ced6fcf 100644 --- a/src/udr/init.c +++ b/src/udr/init.c @@ -64,7 +64,7 @@ static void event_termination(void) { ogs_sbi_nf_instance_t *nf_instance = NULL; - /* Sending NF Instance De-registeration to NRF */ + /* Sending NF Instance De-registration to NRF */ ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance) ogs_sbi_nf_fsm_fini(nf_instance); @@ -113,7 +113,7 @@ static void udr_main(void *data) /* * After ogs_pollset_poll(), ogs_timer_mgr_expire() must be called. * - * The reason is why ogs_timer_mgr_next() can get the corrent value + * The reason is why ogs_timer_mgr_next() can get the current value * when ogs_timer_stop() is called internally in ogs_timer_mgr_expire(). * * You should not use event-queue before ogs_timer_mgr_expire(). diff --git a/src/upf/init.c b/src/upf/init.c index d5779c2ee..85e7f9ee8 100644 --- a/src/upf/init.c +++ b/src/upf/init.c @@ -122,7 +122,7 @@ static void upf_main(void *data) /* * After ogs_pollset_poll(), ogs_timer_mgr_expire() must be called. * - * The reason is why ogs_timer_mgr_next() can get the corrent value + * The reason is why ogs_timer_mgr_next() can get the current value * when ogs_timer_stop() is called internally in ogs_timer_mgr_expire(). * * You should not use event-queue before ogs_timer_mgr_expire(). diff --git a/tests/af/init.c b/tests/af/init.c index d5b2f8ac7..279a9b777 100644 --- a/tests/af/init.c +++ b/tests/af/init.c @@ -73,7 +73,7 @@ static void event_termination(void) { ogs_sbi_nf_instance_t *nf_instance = NULL; - /* Sending NF Instance De-registeration to NRF */ + /* Sending NF Instance De-registration to NRF */ ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance) ogs_sbi_nf_fsm_fini(nf_instance); @@ -117,7 +117,7 @@ static void af_main(void *data) /* * After ogs_pollset_poll(), ogs_timer_mgr_expire() must be called. * - * The reason is why ogs_timer_mgr_next() can get the corrent value + * The reason is why ogs_timer_mgr_next() can get the current value * when ogs_timer_stop() is called internally in ogs_timer_mgr_expire(). * * You should not use event-queue before ogs_timer_mgr_expire(). From d3edce9e9192fd3f07c780cc7a8fad681f970d33 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Sat, 19 Apr 2025 20:56:16 +0900 Subject: [PATCH 06/22] [UDM] Update UE state machine to handle authentication retrieval errors (#3864) - In `udm_ue_state_operational()`: - Wrap the call to `udm_nudr_dr_handle_subscription_authentication()` in an `if` check. - On failure (`false`), log an error via `ogs_error("udm_nudr_dr_handle_subscription_authentication() failed")`. - Transition the FSM to `udm_ue_state_exception` using `OGS_FSM_TRAN()`. This change ensures that failures during subscription authentication REST calls are not silently ignored, and that the UE state machine moves into an exception state for proper error handling and recovery. --- src/udm/ue-sm.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/udm/ue-sm.c b/src/udm/ue-sm.c index 550aea30c..de033e4ef 100644 --- a/src/udm/ue-sm.c +++ b/src/udm/ue-sm.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019-2024 by Sukchan Lee + * Copyright (C) 2019-2025 by Sukchan Lee * * This file is part of Open5GS. * @@ -302,8 +302,12 @@ void udm_ue_state_operational(ogs_fsm_t *s, udm_event_t *e) CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTION_DATA) SWITCH(message->h.resource.component[2]) CASE(OGS_SBI_RESOURCE_NAME_AUTHENTICATION_DATA) - udm_nudr_dr_handle_subscription_authentication( - udm_ue, stream, message); + if (udm_nudr_dr_handle_subscription_authentication( + udm_ue, stream, message) == false) { + ogs_error("udm_nudr_dr_handle_subscription_" + "authentication() failed"); + OGS_FSM_TRAN(s, udm_ue_state_exception); + } break; CASE(OGS_SBI_RESOURCE_NAME_CONTEXT_DATA) From fba00abd7508b9b34ade173c9c87a94cf8760726 Mon Sep 17 00:00:00 2001 From: Pallavi Das Date: Tue, 22 Apr 2025 23:26:34 +0530 Subject: [PATCH 07/22] Typos Fix --- lib/gtp/context.c | 2 +- src/amf/npcf-handler.c | 2 +- src/ausf/ausf-sm.c | 2 +- src/pcf/pcf-sm.c | 2 +- src/sgwc/context.h | 2 +- src/sgwc/pfcp-path.c | 4 ++-- src/sgwu/context.h | 2 +- src/sgwu/pfcp-path.c | 4 ++-- src/sgwu/sxa-handler.c | 2 +- src/smf/context.c | 2 +- src/smf/context.h | 2 +- src/smf/pfcp-path.c | 4 ++-- src/udm/udm-sm.c | 2 +- src/upf/context.h | 2 +- src/upf/pfcp-path.c | 4 ++-- 15 files changed, 19 insertions(+), 19 deletions(-) diff --git a/lib/gtp/context.c b/lib/gtp/context.c index 5c144b54f..e661a22ef 100644 --- a/lib/gtp/context.c +++ b/lib/gtp/context.c @@ -485,7 +485,7 @@ int ogs_gtp_context_parse_config(const char *local, const char *remote) * * In the following configuration, * 127.0.0.4, 127.0.0.5 and 2001:db8:cafe::1 are ignored - * on PFCP Assocation Response message's + * on PFCP Association Response message's * user plane IP resource information. * * gtpu: diff --git a/src/amf/npcf-handler.c b/src/amf/npcf-handler.c index 71b90b0fc..a21cbfb74 100644 --- a/src/amf/npcf-handler.c +++ b/src/amf/npcf-handler.c @@ -94,7 +94,7 @@ int amf_npcf_am_policy_control_handle_create( } if (!message.h.resource.component[1]) { - ogs_error("[%s] No Assocation ID [%s]", + ogs_error("[%s] No Association ID [%s]", amf_ue->supi, recvmsg->http.location); ogs_sbi_header_free(&header); diff --git a/src/ausf/ausf-sm.c b/src/ausf/ausf-sm.c index 2546180c5..72e7c07d8 100644 --- a/src/ausf/ausf-sm.c +++ b/src/ausf/ausf-sm.c @@ -462,7 +462,7 @@ void ausf_state_operational(ogs_fsm_t *s, ausf_event_t *e) ogs_error("Cannot receive SBI message"); if (!stream) { - ogs_error("STREAM has alreadt been removed [%d]", + ogs_error("STREAM has already been removed [%d]", sbi_xact->assoc_stream_id); break; } diff --git a/src/pcf/pcf-sm.c b/src/pcf/pcf-sm.c index 700320500..3af52fb18 100644 --- a/src/pcf/pcf-sm.c +++ b/src/pcf/pcf-sm.c @@ -789,7 +789,7 @@ void pcf_state_operational(ogs_fsm_t *s, pcf_event_t *e) ogs_error("Cannot receive SBI message"); if (!stream) { - ogs_error("STREAM has alreadt been removed [%d]", + ogs_error("STREAM has already been removed [%d]", sbi_xact->assoc_stream_id); break; } diff --git a/src/sgwc/context.h b/src/sgwc/context.h index f028af681..2d2be2d1c 100644 --- a/src/sgwc/context.h +++ b/src/sgwc/context.h @@ -83,7 +83,7 @@ typedef struct sgwc_sess_s { uint32_t sgw_s5c_teid; /* SGW-S5C-TEID is derived from NODE */ uint32_t pgw_s5c_teid; /* PGW-S5C-TEID is received from PGW */ - uint64_t sgwc_sxa_seid; /* SGW-C SEID is dervied from NODE */ + uint64_t sgwc_sxa_seid; /* SGW-C SEID is derived from NODE */ uint64_t sgwu_sxa_seid; /* SGW-U SEID is received from Peer */ /* APN Configuration */ diff --git a/src/sgwc/pfcp-path.c b/src/sgwc/pfcp-path.c index 1483e99a1..b801110fe 100644 --- a/src/sgwc/pfcp-path.c +++ b/src/sgwc/pfcp-path.c @@ -19,7 +19,7 @@ #include "pfcp-path.h" -static void pfcp_node_fsm_init(ogs_pfcp_node_t *node, bool try_to_assoicate) +static void pfcp_node_fsm_init(ogs_pfcp_node_t *node, bool try_to_associate) { sgwc_event_t e; @@ -28,7 +28,7 @@ static void pfcp_node_fsm_init(ogs_pfcp_node_t *node, bool try_to_assoicate) memset(&e, 0, sizeof(e)); e.pfcp_node = node; - if (try_to_assoicate == true) { + if (try_to_associate == true) { node->t_association = ogs_timer_add(ogs_app()->timer_mgr, sgwc_timer_pfcp_association, node); ogs_assert(node->t_association); diff --git a/src/sgwu/context.h b/src/sgwu/context.h index dc322eb51..a5e72ae3c 100644 --- a/src/sgwu/context.h +++ b/src/sgwu/context.h @@ -52,7 +52,7 @@ typedef struct sgwu_sess_s { ogs_pfcp_sess_t pfcp; - uint64_t sgwu_sxa_seid; /* SGW-U SEID is dervied from INDEX */ + uint64_t sgwu_sxa_seid; /* SGW-U SEID is derived from INDEX */ struct { uint64_t seid; ogs_ip_t ip; diff --git a/src/sgwu/pfcp-path.c b/src/sgwu/pfcp-path.c index 3cdd32053..ac0671cb4 100644 --- a/src/sgwu/pfcp-path.c +++ b/src/sgwu/pfcp-path.c @@ -19,7 +19,7 @@ #include "pfcp-path.h" -static void pfcp_node_fsm_init(ogs_pfcp_node_t *node, bool try_to_assoicate) +static void pfcp_node_fsm_init(ogs_pfcp_node_t *node, bool try_to_associate) { sgwu_event_t e; @@ -28,7 +28,7 @@ static void pfcp_node_fsm_init(ogs_pfcp_node_t *node, bool try_to_assoicate) memset(&e, 0, sizeof(e)); e.pfcp_node = node; - if (try_to_assoicate == true) { + if (try_to_associate == true) { node->t_association = ogs_timer_add(ogs_app()->timer_mgr, sgwu_timer_association, node); ogs_assert(node->t_association); diff --git a/src/sgwu/sxa-handler.c b/src/sgwu/sxa-handler.c index dd8ad014a..29b2d8522 100644 --- a/src/sgwu/sxa-handler.c +++ b/src/sgwu/sxa-handler.c @@ -363,7 +363,7 @@ void sgwu_sxa_handle_session_report_response( ogs_pfcp_xact_commit(xact); - ogs_debug("Session report resopnse"); + ogs_debug("Session report response"); cause_value = OGS_PFCP_CAUSE_REQUEST_ACCEPTED; diff --git a/src/smf/context.c b/src/smf/context.c index 0686a4fee..58936215a 100644 --- a/src/smf/context.c +++ b/src/smf/context.c @@ -1505,7 +1505,7 @@ smf_sess_t *smf_sess_add_by_sbi_message(ogs_sbi_message_t *message) } if (SmContextCreateData->is_pdu_session_id == false) { - ogs_error("PDU session identitiy is unassigned"); + ogs_error("PDU session identity is unassigned"); return NULL; } diff --git a/src/smf/context.h b/src/smf/context.h index b43fc6b84..84c229278 100644 --- a/src/smf/context.h +++ b/src/smf/context.h @@ -254,7 +254,7 @@ typedef struct smf_sess_s { uint32_t sgw_s5c_teid; /* SGW-S5C-TEID is received from SGW */ ogs_ip_t sgw_s5c_ip; /* SGW-S5C IPv4/IPv6 */ - uint64_t smf_n4_seid; /* SMF SEID is dervied from NODE */ + uint64_t smf_n4_seid; /* SMF SEID is derived from NODE */ uint64_t upf_n4_seid; /* UPF SEID is received from Peer */ uint32_t upf_n3_teid; /* UPF-N3 TEID */ diff --git a/src/smf/pfcp-path.c b/src/smf/pfcp-path.c index b560cfa02..0219f59b6 100644 --- a/src/smf/pfcp-path.c +++ b/src/smf/pfcp-path.c @@ -59,7 +59,7 @@ uint32_t smf_pfcp_urr_usage_report_trigger2diam_gy_reporting_reason(ogs_pfcp_usa return OGS_DIAM_GY_REPORTING_REASON_UNUSED_QUOTA_TIMER; } -static void pfcp_node_fsm_init(ogs_pfcp_node_t *node, bool try_to_assoicate) +static void pfcp_node_fsm_init(ogs_pfcp_node_t *node, bool try_to_associate) { smf_event_t e; @@ -68,7 +68,7 @@ static void pfcp_node_fsm_init(ogs_pfcp_node_t *node, bool try_to_assoicate) memset(&e, 0, sizeof(e)); e.pfcp_node = node; - if (try_to_assoicate == true) { + if (try_to_associate == true) { node->t_association = ogs_timer_add(ogs_app()->timer_mgr, smf_timer_pfcp_association, node); ogs_assert(node->t_association); diff --git a/src/udm/udm-sm.c b/src/udm/udm-sm.c index 1c1b0995f..d626d036f 100644 --- a/src/udm/udm-sm.c +++ b/src/udm/udm-sm.c @@ -597,7 +597,7 @@ void udm_state_operational(ogs_fsm_t *s, udm_event_t *e) ogs_error("Cannot receive SBI message"); if (!stream) { - ogs_error("STREAM has alreadt been removed [%d]", + ogs_error("STREAM has already been removed [%d]", sbi_xact->assoc_stream_id); break; } diff --git a/src/upf/context.h b/src/upf/context.h index ee44a52f2..08cf996f4 100644 --- a/src/upf/context.h +++ b/src/upf/context.h @@ -105,7 +105,7 @@ typedef struct upf_sess_s { ogs_pfcp_sess_t pfcp; - uint64_t upf_n4_seid; /* UPF SEID is dervied from NODE */ + uint64_t upf_n4_seid; /* UPF SEID is derived from NODE */ struct { uint64_t seid; ogs_ip_t ip; diff --git a/src/upf/pfcp-path.c b/src/upf/pfcp-path.c index ad3c3577a..114e58822 100644 --- a/src/upf/pfcp-path.c +++ b/src/upf/pfcp-path.c @@ -22,7 +22,7 @@ #include "pfcp-path.h" #include "n4-build.h" -static void pfcp_node_fsm_init(ogs_pfcp_node_t *node, bool try_to_assoicate) +static void pfcp_node_fsm_init(ogs_pfcp_node_t *node, bool try_to_associate) { upf_event_t e; @@ -31,7 +31,7 @@ static void pfcp_node_fsm_init(ogs_pfcp_node_t *node, bool try_to_assoicate) memset(&e, 0, sizeof(e)); e.pfcp_node = node; - if (try_to_assoicate == true) { + if (try_to_associate == true) { node->t_association = ogs_timer_add(ogs_app()->timer_mgr, upf_timer_association, node); ogs_assert(node->t_association); From 4c2f40d2c2375acf3fca4ccfd7e98d30d971d75d Mon Sep 17 00:00:00 2001 From: Spencer Sevilla Date: Fri, 25 Apr 2025 11:31:54 -0700 Subject: [PATCH 08/22] more verbose DNN reject message --- src/amf/gmm-handler.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/amf/gmm-handler.c b/src/amf/gmm-handler.c index 30deb4cdc..c6710eeba 100644 --- a/src/amf/gmm-handler.c +++ b/src/amf/gmm-handler.c @@ -1358,8 +1358,8 @@ int gmm_handle_ul_nas_transport(ran_ue_t *ran_ue, amf_ue_t *amf_ue, } if (!selected_slice || !sess->dnn) { - ogs_warn("[%s] DNN Not Supported OR " - "Not Subscribed in the Slice", amf_ue->supi); + ogs_warn("[%s] Ue requested DNN \"%s\" Not Supported OR " + "Not Subscribed in the Slice", amf_ue->supi, dnn->value); r = nas_5gs_send_gmm_status(amf_ue, OGS_5GMM_CAUSE_DNN_NOT_SUPPORTED_OR_NOT_SUBSCRIBED_IN_THE_SLICE); ogs_expect(r == OGS_OK); From 7b40d5a3f1080f088c653abfdc01f3adfac5d3cd Mon Sep 17 00:00:00 2001 From: ethonshield Date: Tue, 29 Apr 2025 12:48:34 +0200 Subject: [PATCH 09/22] Add tutorial doc on how to configure Open5GS with 5G-Sharp-Orchestrator --- .../06-Open5GS-with-5G-Sharp-Orchestrator.md | 478 ++++++++++++++++++ 1 file changed, 478 insertions(+) create mode 100644 docs/_docs/tutorial/06-Open5GS-with-5G-Sharp-Orchestrator.md diff --git a/docs/_docs/tutorial/06-Open5GS-with-5G-Sharp-Orchestrator.md b/docs/_docs/tutorial/06-Open5GS-with-5G-Sharp-Orchestrator.md new file mode 100644 index 000000000..2ee7d4033 --- /dev/null +++ b/docs/_docs/tutorial/06-Open5GS-with-5G-Sharp-Orchestrator.md @@ -0,0 +1,478 @@ +--- +title: Open5GS with 5G Sharp Orchestrator +--- + +This tutorial is a guide to configure the tool 5G Sharp Orchestrator with Open5GS. + +5G Sharp Orchestrator is a tool that serves as a comprehensive wrapper for configuring, deploying and monitoring 5G open-source network components, simplifying the orchestration process. + +For more information on 5G Sharp Orchestrator please visit: https://github.com/Ethon-Shield/5g-sharp-orchestrator + +![Basic Execution Example](https://raw.githubusercontent.com/Ethon-Shield/5g-sharp-orchestrator/9eddaf0c19d8333708271f1e3d6348735e32ae90/images/basic_execution_example.png) + + +# Usage + +To correctly execute the 5G Sharp Orchestrator with Open5GS you will need to: + +**0. Install prerequisites** +**1. Configure the project** +**2. Check the configuration is valid** +**3. Execute the tool** + +This tutorial has been described with the following setup: +- Physical machine: + - i7 processor + - Ubuntu 22.04 LTS + - User "test" + - Connectivity - Offline + - Open5GS cloned and compiled in /home/test/open5gs + - srsRAN cloned and compiled in /home/test/srsRAN_Project +- Network parameters: + - MCC: 001 + - MNC: 01 + - TAC: 1 +- SDR device: + - Ettus B200 mini + +## 0. Install prerequisites + +To be able to use the 5G Sharp Orchestrator tool, you will need to meet the following prerequisites. + +
+Software prerequisites + +This project needs certain binaries to be installed. + +- The project has been successfully tested with **Ubuntu 22.04** +- UHD built from source (https://files.ettus.com/manual/page_build_guide.html) +- docker **version 19.03.0 or higher** (https://docs.docker.com/engine/install/ubuntu/) +``` +# User going to be used should be in the docker group +sudo usermod -aG docker +newgrp docker +``` +- docker-compose **version 1.29.2 or higher** (https://docs.docker.com/compose/install/linux/) +- tmux **version 3.5a** (https://github.com/tmux/tmux/releases) + +```bash +wget https://github.com/tmux/tmux/releases/download/3.5a/tmux-3.5a.tar.gz +tar -zxf tmux-3.5a.tar.gz +cd tmux-3.5a +./configure +make +sudo make install +``` + +- wireshark, tshark, expect + +```bash +sudo add-apt-repository ppa:wireshark-dev/stable +sudo apt update +sudo apt install wireshark tshark expect +``` + +
+
+Install Open5GS Core + +Official documentation: https://open5gs.org/open5gs/docs/guide/02-building-open5gs-from-sources/ + +To work with Open5GS core, it is recommended to build the project from source. + +**1. Getting MongoDB** + +- Install GNU Privacy Guard tool: + +``` +sudo apt update +sudo apt install gnupg +``` + +- Import the public key used by the package management system: + +``` +curl -fsSL https://pgp.mongodb.com/server-7.0.asc | sudo gpg -o /usr/share/keyrings/mongodb-server-7.0.gpg --dearmor + +echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-7.0.gpg ] https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/7.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-7.0.list +``` + +- Install the MongoDB packages: +``` +sudo apt update +sudo apt install -y mongodb-org +``` + +**NOTE**: MongoDB service needs to be running in order to execute the project. This can be done using the command ``sudo systemctl start mongod `` + +**2. Building Open5GS** + +Install the required dependencies: + +``` +sudo apt install python3-pip python3-setuptools python3-wheel ninja-build build-essential flex bison git cmake libsctp-dev libgnutls28-dev libgcrypt-dev libssl-dev libidn11-dev libmongoc-dev libbson-dev libyaml-dev libnghttp2-dev libmicrohttpd-dev libcurl4-gnutls-dev libnghttp2-dev libtins-dev libtalloc-dev meson +``` +Clone the official project repository: +``` +git clone https://github.com/open5gs/open5gs +``` +Compile with meson and build with ninja: +``` +cd open5gs/ meson build --prefix=`pwd`/install +ninja -C build +``` +Check wether the compilation is correct: +``` + ./build/tests/registration/registration +``` +Run all test programs: +``` +cd build +sudo meson test -v +``` +Perform the installation process: +``` +cd build +ninja install +cd ../ +``` +
+ +
+Install srsRAN gNB + +Official documentation: https://docs.srsran.com/projects/project/en/latest/user_manuals/source/installation.html + +**1. Installing build tools and dependencies** + +The required build tools and dependencies for the project can be installed in Ubuntu using the following command: +``` +sudo apt-get install cmake make gcc g++ pkg-config libfftw3-dev libmbedtls-dev libsctp-dev libyaml-cpp-dev libgtest-devg +``` + +**2. Clone and build** + +Clone the project repository: +``` +git clone https://github.com/srsRAN/srsRAN_Project.git +``` + +Build the code-base: +``` +cd srsRAN_Project +mkdir build +cd build +cmake ../ +make -j $(nproc) +make test -j $(nproc) +sudo make install +``` +
+ +
+Hardware prerequisites + + +- USRP devices. +- USB 3.0 port to connect the SDR. +- It is recommended to at least have an i7 processor. + +
+ + +## 1. Configuring the project + +Once the prerequisites have been fullfilled, the next step is to setup the 5G Sharp Orchestrator. First of all, clone the repository: + +``` +cd ~/ +git clone https://github.com/Ethon-Shield/5g-sharp-orchestrator.git +``` + +To configure the 5G Sharp Orchestrator with Open5GS you will need to modify the corresponding parameters in the file `./conf/sharp-orchestrator.src` . In this file you will be able to set different network parameters such as the MCC, MNC or TAC, encryption and integrity alogrithms, as well as defining the file paths of the corresponding binaries. + +The following variables are set based on the example setup described at the start of the tutorial. + +**SHARP ORCHESTRATOR**: +- **SHARP_ORCHESTRATOR_IP_ADDRESS**=127.0.0.1 +- **SHARP_ORCHESTRATOR_USERNAME**="test" +- **SHARP_ORCHESTRATOR_WORKING_DIR**="/home/test/5g-sharp-orhcestrator/" + +**GENERAL**: + +- **MCC**=001 +- **MNC**=01 +- **TAC**=1 +- **DEBUG**="false" +- **DNS_IP_ADDRESS**="8.8.8.8" +- **DEPLOY_NRCORE_ONLY**="false" +- **BACKUP_DIR_PREFIX**="" + +**NRCORE**: + +- **NRCORE_TECH**=OPEN5GS +- **INT_ALGO_PRIORITY_LIST**=NIA1,NIA2,NIA0 +- **CIPH_ALGO_PRIORITY_LIST**=NEA1,NEA2,NEA0 +- **NRCORE_OPEN5GS_WD**="/home/test/open5gs" + +**GNB**: + +- **GNB_TECH**=SRS +- **GNB_IP_ADDRESS**=127.0.0.1 +- **GNB_USERNAME**="test" +- **GNB_WORKING_DIR**="/home/test/Desktop/gnb" +- **ARFCN**="641280" +- **SRS_GNB_BIN**="/home/test/srsRAN_Project/build/apps/gnb/gnb" +- **BAND**="78" +- **CHANNEL_BW**="20" +- **SCS**="15" + +### SUDOERS file + +It will be necessary to modify /etc/.sudoers file (via visudo for example) in order to be able to execute certain commands that need root privileges: + +```bash +test ALL=(ALL) NOPASSWD: \ +/usr/bin/kill -9 *, \ +/usr/bin/chown -R * /tmp, \ +/usr/bin/chown -R * /logs, \ +/usr/sbin/ip tuntap add name ogstun mode tun, \ +/usr/sbin/ip addr del 10.45.0.1/16 dev ogstun, \ +/usr/sbin/ip addr add 10.45.0.1/16 dev ogstun, \ +/usr/sbin/ip addr del 2001\:db8\:cafe\:\:1/48 dev ogstun, \ +/usr/sbin/ip addr add 2001\:db8\:cafe\:\:1/48 dev ogstun, \ +/usr/sbin/ip link set ogstun up, \ +/usr/sbin/sysctl net.ipv4.conf.all.forwarding=1, \ +/usr/sbin/iptables -P FORWARD ACCEPT, \ +/usr/sbin/iptables -S, \ +/usr/sbin/ip route del *, \ +/usr/sbin/ip route add *, \ +/usr/bin/unbuffer *, \ +/usr/bin/kill -9 * +``` + +### SSH KEYS + +Furthermore, although in this example setup we are only using one physical machine, the nodes will talk to each other via ssh. Consequently, it is important to store the public ssh key of the corresponding user. + +1. Generate ssh key pair: `ssh-key-gen -t rsa` +2. Copy public pair into remote machine (in this example setup - localhost): `ssh-copy-id -i ~/.ssh/id_rsa.pub test@127.0.0.1` + + +## 2. Checking the configuation is valid + +Once the project has been configured accordingly, check if it has been correctly configured executing the next script: `./bin/check_conf.sh`. All checks should have a **YES**. + +
+ Example output + +``` +################################## +Checking basic variables +################################## +BASIC variables are OK + +################################## +Checking necessary binaries +################################## +tshark ... YES +expect ... YES +tmux ... YES +uhd_find_devices ... YES +uhd_usrp_probe ... YES +open5gs-nrfd ... YES +open5gs-scpd ... YES +open5gs-amfd ... YES +open5gs-smfd ... YES +open5gs-upfd ... YES +open5gs-ausfd ... YES +open5gs-udmd ... YES +open5gs-pcfd ... YES +open5gs-nssfd ... YES +open5gs-bsfd ... YES +open5gs-udrd ... YES + +################################## +Checking CORE IP address, username and working dir +################################## + +CORE IP ADDRESS ... YES +CORE USERNAME ... YES +CORE WORKING DIR ... YES + +Checking if open5gs services are active + +MongoDB is running ... YES + +################################## +Checking SSH connections +################################## + +CORE --> GNB ... YES +GNB --> CORE ... YES + +################################## +Checking necessary repositories & binaries +################################## + +OPEN5GS CORE + /home/test/open5gs/ directory ... YES + NOTES: + - /home/test/open5gs/ in TAG v2.7.2-65-g6d80d4322 +gNB + SRS gnb bin ... YES + +################################## +Checking sudoers file +################################## + +NOPASSWD in ORCH & CORE for test for command /usr/bin/kill -9 \* ... YES +NOPASSWD in ORCH & CORE for test for command /usr/bin/chown -R \* /tmp ... YES +NOPASSWD in ORCH & CORE for test for command /usr/bin/chown -R \* /logs ... YES +NOPASSWD in ORCH & CORE for test for command /usr/sbin/ip tuntap add name ogstun mode tun ... YES +NOPASSWD in ORCH & CORE for test for command /usr/sbin/ip addr del 10.45.0.1/16 dev ogstun ... YES +NOPASSWD in ORCH & CORE for test for command /usr/sbin/ip addr add 10.45.0.1/16 dev ogstun ... YES +NOPASSWD in ORCH & CORE for test for command /usr/sbin/ip addr del 2001\:db8\:cafe\:\:1/48 dev ogstun ... YES +NOPASSWD in ORCH & CORE for test for command /usr/sbin/ip addr add 2001\:db8\:cafe\:\:1/48 dev ogstun ... YES +NOPASSWD in ORCH & CORE for test for command /usr/sbin/ip link set ogstun up ... YES +NOPASSWD in ORCH & CORE for test for command /usr/sbin/sysctl net.ipv4.conf.all.forwarding\=1 ... YES +NOPASSWD in ORCH & CORE for test for command /usr/sbin/iptables -P FORWARD ACCEPT ... YES +NOPASSWD in ORCH & CORE for test for command /usr/sbin/iptables -S ... YES +NOPASSWD in GNB for test for command /usr/sbin/ip route del \* in GNB ... YES +NOPASSWD in GNB for test for command /usr/sbin/ip route add \* in GNB ... YES +NOPASSWD in GNB for test for command /usr/bin/unbuffer \* in GNB ... YES +NOPASSWD in GNB for test for command /usr/bin/kill -9 \* in GNB ... YES + +################################## +Checking sharp-orchestrator.src parameters +################################## + +MCC 001 ... YES +MNC 01 ... YES +DEBUG false ... YES +DEPLOY_NRCORE_ONLY false ... YES +DNS_IP_ADDRESS 8.8.8.8 ... YES +AMF_IP_ADDRESS 127.0.0.100 ... YES +SHARP_ORCHESTRATOR_IP_ADDRESS 127.0.0.1 ... YES +NRCORE_IP_ADDRESS 127.0.0.1 ... YES +GNB_IP_ADDRESS 127.0.0.1 ... YES + +################################## +Checking gNB directory +################################## + +GNB directory ... YES +``` + +
+ +## 3. Executing the tool + +After checking the configuration file and setting every paramater correctly, you will be able to start the orchestration process. + +##### STARTING THE ORCHESTRATOR APP + +To start the orchestrator app execute the following command: +```bash +./tui.sh +``` + +You will have an interactive menu to perform all the needed actions. + +![Main Menu](https://raw.githubusercontent.com/Ethon-Shield/5g-sharp-orchestrator/9eddaf0c19d8333708271f1e3d6348735e32ae90/images/MAINMENU.png) + +##### STARTING THE NETWORK + +Choose the "Start network" option in the interactive menu --> "1" + +##### STOPPING THE NETWORK + +Choose the "Stop network" option in the interactive menu --> "2" + +##### UPDATE GNB PARAMETERS ON REAL-TIME + +Some parameters in the gNB can be updated on real-time. This is done to prevent the undeployment of the core network and slowing the whole process. + +The current supported parameters for the srs gNB to be updated are: +- ARFCN +- BAND +- CHANNEL_BW +- SCS + +Choose the "Change network parameters" option in the interactive menu --> "3" + +This will show a sub menu with the different options: +- Setting the different parameters +- Updating them + +![Submenu Update Parameters](https://raw.githubusercontent.com/Ethon-Shield/5g-sharp-orchestrator/9eddaf0c19d8333708271f1e3d6348735e32ae90/images/SUBMENU_update_parameters.png) + +Before updating any parameter, you need to set the value. For that, choose the corresponding "set" option and the value to set will be asked. +The new set value will appear in the menu, as it is shown in the images below + +![Submenu Update Parameters Set ARFCN](https://raw.githubusercontent.com/Ethon-Shield/5g-sharp-orchestrator/9eddaf0c19d8333708271f1e3d6348735e32ae90/images/SUBMENU_update_parameters_set_arfcn.png) + + +![Submenu Update Parameters ARFCN Set](https://raw.githubusercontent.com/Ethon-Shield/5g-sharp-orchestrator/9eddaf0c19d8333708271f1e3d6348735e32ae90/images/SUBMENU_update_parameters_arfcn_setted.png) + + +After setting all the values you want to update, choose the "Update parameters" option in the interactive menu for the changes to take place. +This action will stop the running gNB instance and start a new one with the updated parameters. +Any error in the gNB execution due to invalid parameters selection will be prompted in the log screen. + + +##### BACKING UP FILES DURING EXECUTION + +Stopping the network will automatically perform a backup. This options is used if you want to perform a backup during the execution without stopping the network. +The backup will be saved in the sharp-orchestrator/backups directory. + +Making a backup will save the following files: +``` +├── logs -> DIR that includes all the logs from the network nodes +├── pcaps -> DIR that includes all the pcaps from the network nodes +├── conf -> DIR that includes the latest configuration files of the network nodes +└── sharp_orchestrator.log -> Orchestration log +``` + +Choose the "Make backup" option in the interactive menu --> "4" + +##### MANAGE SUBSCRIBERS IN DATABASE + +To be able to connect subscribers to the deployed network they need to be provisioned in the corresponding databases. + +Choose the "Edit Database" option in the interactive menu --> "5" + +This will show a sub menu with the different options: +- Setting the different parameters (IMSI, KI, OPC) +- Adding a subscriber to the database - needed parameters: IMSI, KI, OPC +- Updating a subscriber in the database - needed parameters: IMSI, KI, OPC +- Removing a subscriber from the database - needed parameters: IMSI + +![Submenu Edit Database](https://raw.githubusercontent.com/Ethon-Shield/5g-sharp-orchestrator/9eddaf0c19d8333708271f1e3d6348735e32ae90/images/SUBMENU_edit_database.png) + + +Before performing an action to a subscriber, you need to add the required information. For that set the different parameters. + +The next image shows an example of setting the IMSI: + +![Submenu Edit Database Set IMSI](https://raw.githubusercontent.com/Ethon-Shield/5g-sharp-orchestrator/9eddaf0c19d8333708271f1e3d6348735e32ae90/images/SUBMENU_edit_database_set_imsi.png) + + +After setting the IMSI, you would be able to remove it from the database, by chossing the option "Remove subscriber from the database" --> 6 + +![Submenu Edit Database Remove Subscriber](https://raw.githubusercontent.com/Ethon-Shield/5g-sharp-orchestrator/9eddaf0c19d8333708271f1e3d6348735e32ae90/images/SUBMENU_edit_database_remove_subscriber.png) + + + + +# More configuration options + +- If you only want to deploy the Open5GS nrcore network without the radio node, set the DEPLOY_NRCORE_ONLY variable to "true" + + +# Viewing PCAP files + +- Go to Analyze --> Enabled Protocols --> check the box mac_nr and mac_nr_udp +- Sometimes, when debugging the PCAP files, the traffic is encrypted using EEA0. To view this traffic, in Wireshark go to Edit -> Preferences -> Protocols -> NAS-5GS -> check box "Try to detect and decode 5G-EA0 ciphered message" + + From 3706479582d428c0badb2d9dd0738023984987e5 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Mon, 5 May 2025 07:55:45 +0900 Subject: [PATCH 10/22] [ipfw] guard token parsing loop against buffer overflow The token parsing loop in ogs_ipfw_compile_rule() lacked a bound on the number of tokens stored in the 'av' array. This could overflow the stack buffer when parsing overly long flow descriptions. Add a check to ensure 'i' remains below MAX_NUM_OF_TOKEN-2 before assigning to 'av[i]'. --- lib/ipfw/ogs-ipfw.c | 2 +- src/udm/udm-sm.c | 2 +- src/udm/ue-sm.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ipfw/ogs-ipfw.c b/lib/ipfw/ogs-ipfw.c index 0140e94a9..1066ba85a 100644 --- a/lib/ipfw/ogs-ipfw.c +++ b/lib/ipfw/ogs-ipfw.c @@ -79,7 +79,7 @@ int ogs_ipfw_compile_rule(ogs_ipfw_rule_t *ipfw_rule, char *flow_description) /* ADDR */ i = 2; token = ogs_strtok_r(NULL, " ", &saveptr); - while (token != NULL) { + while ((token != NULL) && (i < (MAX_NUM_OF_TOKEN-2))) { av[i++] = token; token = ogs_strtok_r(NULL, " ", &saveptr); } diff --git a/src/udm/udm-sm.c b/src/udm/udm-sm.c index d626d036f..95cad6714 100644 --- a/src/udm/udm-sm.c +++ b/src/udm/udm-sm.c @@ -479,7 +479,7 @@ void udm_state_operational(ogs_fsm_t *s, udm_event_t *e) ogs_fsm_dispatch(&udm_ue->sm, e); if (OGS_FSM_CHECK(&udm_ue->sm, udm_ue_state_exception)) { - ogs_error("[%s] State machine exception", udm_ue->suci); + ogs_warn("[%s] State machine exception", udm_ue->suci); udm_ue_remove(udm_ue); } END diff --git a/src/udm/ue-sm.c b/src/udm/ue-sm.c index de033e4ef..54e196e7b 100644 --- a/src/udm/ue-sm.c +++ b/src/udm/ue-sm.c @@ -304,7 +304,7 @@ void udm_ue_state_operational(ogs_fsm_t *s, udm_event_t *e) CASE(OGS_SBI_RESOURCE_NAME_AUTHENTICATION_DATA) if (udm_nudr_dr_handle_subscription_authentication( udm_ue, stream, message) == false) { - ogs_error("udm_nudr_dr_handle_subscription_" + ogs_warn("udm_nudr_dr_handle_subscription_" "authentication() failed"); OGS_FSM_TRAN(s, udm_ue_state_exception); } From e0dc9360160b28f75d35141e38f27af8a3c4d6ca Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Mon, 5 May 2025 09:32:25 +0900 Subject: [PATCH 11/22] [NRF] reject SELF nf instance in SBI operations (#3845) Prevent the NRF from processing requests that target its own instance ID. This prevents a denial of service vulnerability. If an SBI request attempts to delete or modify the local NRF instance, respond with 404 Not Found and log an error, avoiding a crash due to the state machine assertion. --- src/nrf/nrf-sm.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/nrf/nrf-sm.c b/src/nrf/nrf-sm.c index 1a5258404..1376ad83d 100644 --- a/src/nrf/nrf-sm.c +++ b/src/nrf/nrf-sm.c @@ -163,6 +163,16 @@ void nrf_state_operational(ogs_fsm_t *s, nrf_event_t *e) &message, "Not found", message.h.resource.component[1], NULL)); END + } else { + if (NF_INSTANCE_ID_IS_SELF(nf_instance->id)) { + ogs_error("SELF Not allowed [%s]", nf_instance->id); + ogs_assert(true == + ogs_sbi_server_send_error(stream, + OGS_SBI_HTTP_STATUS_NOT_FOUND, + &message, "SELF Not allowed", + nf_instance->id, NULL)); + break; + } } if (nf_instance) { From c145fc88aaccf2b2bc004d4b454339d7ffd0cca7 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Mon, 5 May 2025 09:54:29 +0900 Subject: [PATCH 12/22] [NRF] prevent invalid NF type registration DoS (#3846) Ensure that NFs with invalid types are rejected and never added, preventing the denial-of-service crash. --- src/nrf/nf-sm.c | 16 ++++++++++------ src/nrf/nrf-sm.c | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/nrf/nf-sm.c b/src/nrf/nf-sm.c index 7ab6ba2e7..e632bab99 100644 --- a/src/nrf/nf-sm.c +++ b/src/nrf/nf-sm.c @@ -81,7 +81,7 @@ void nrf_nf_state_final(ogs_fsm_t *s, nrf_event_t *e) void nrf_nf_state_will_register(ogs_fsm_t *s, nrf_event_t *e) { - bool handled; + bool handled = false; ogs_sbi_nf_instance_t *nf_instance = NULL; ogs_sbi_stream_t *stream = NULL; @@ -128,7 +128,9 @@ void nrf_nf_state_will_register(ogs_fsm_t *s, nrf_event_t *e) handled = nrf_nnrf_handle_nf_register( nf_instance, stream, message); - if (handled == false) + if (handled == true) + OGS_FSM_TRAN(s, nrf_nf_state_registered); + else OGS_FSM_TRAN(s, nrf_nf_state_exception); break; @@ -139,6 +141,7 @@ void nrf_nf_state_will_register(ogs_fsm_t *s, nrf_event_t *e) ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_METHOD_NOT_ALLOWED, message, "Invalid HTTP method", message->h.method, NULL)); + OGS_FSM_TRAN(s, nrf_nf_state_exception); END break; @@ -150,6 +153,7 @@ void nrf_nf_state_will_register(ogs_fsm_t *s, nrf_event_t *e) OGS_SBI_HTTP_STATUS_METHOD_NOT_ALLOWED, message, "Invalid resource name", message->h.resource.component[0], NULL)); + OGS_FSM_TRAN(s, nrf_nf_state_exception); END break; @@ -161,9 +165,8 @@ void nrf_nf_state_will_register(ogs_fsm_t *s, nrf_event_t *e) OGS_SBI_HTTP_STATUS_METHOD_NOT_ALLOWED, message, "Invalid resource name", message->h.service.name, NULL)); + OGS_FSM_TRAN(s, nrf_nf_state_exception); END - - OGS_FSM_TRAN(s, nrf_nf_state_registered); break; default: @@ -175,7 +178,6 @@ void nrf_nf_state_will_register(ogs_fsm_t *s, nrf_event_t *e) message, "Unknown event", nrf_event_get_name(e), NULL)); OGS_FSM_TRAN(s, nrf_nf_state_exception); - break; } } @@ -278,6 +280,7 @@ void nrf_nf_state_registered(ogs_fsm_t *s, nrf_event_t *e) ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_METHOD_NOT_ALLOWED, message, "Invalid HTTP method", message->h.method, NULL)); + OGS_FSM_TRAN(s, nrf_nf_state_exception); END break; @@ -289,6 +292,7 @@ void nrf_nf_state_registered(ogs_fsm_t *s, nrf_event_t *e) OGS_SBI_HTTP_STATUS_METHOD_NOT_ALLOWED, message, "Invalid resource name", message->h.resource.component[0], NULL)); + OGS_FSM_TRAN(s, nrf_nf_state_exception); END break; @@ -300,6 +304,7 @@ void nrf_nf_state_registered(ogs_fsm_t *s, nrf_event_t *e) OGS_SBI_HTTP_STATUS_METHOD_NOT_ALLOWED, message, "Invalid resource name", message->h.service.name, NULL)); + OGS_FSM_TRAN(s, nrf_nf_state_exception); END break; @@ -312,7 +317,6 @@ void nrf_nf_state_registered(ogs_fsm_t *s, nrf_event_t *e) message, "Unknown event", nrf_event_get_name(e), NULL)); OGS_FSM_TRAN(s, nrf_nf_state_exception); - break; } } diff --git a/src/nrf/nrf-sm.c b/src/nrf/nrf-sm.c index 1376ad83d..1135bd54e 100644 --- a/src/nrf/nrf-sm.c +++ b/src/nrf/nrf-sm.c @@ -168,7 +168,7 @@ void nrf_state_operational(ogs_fsm_t *s, nrf_event_t *e) ogs_error("SELF Not allowed [%s]", nf_instance->id); ogs_assert(true == ogs_sbi_server_send_error(stream, - OGS_SBI_HTTP_STATUS_NOT_FOUND, + OGS_SBI_HTTP_STATUS_FORBIDDEN, &message, "SELF Not allowed", nf_instance->id, NULL)); break; From 2231e48870d1912cfff67b79a0bb7f615fa63441 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Mon, 5 May 2025 10:14:48 +0900 Subject: [PATCH 13/22] [AMF] guard ran_ue to avoid assertion crash [#3851] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If `ran_ue` has already been removed, log a warning using the UE’s SUPI instead of triggering an assertion failure. --- src/amf/nsmf-handler.c | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/src/amf/nsmf-handler.c b/src/amf/nsmf-handler.c index c681ad156..ca52c993e 100644 --- a/src/amf/nsmf-handler.c +++ b/src/amf/nsmf-handler.c @@ -586,15 +586,19 @@ int amf_nsmf_pdusession_handle_update_sm_context( * 6. UEContextReleaseComplete */ ogs_warn("PDUSessionResourceSetupResponse(Unsuccessful)"); - ogs_assert(ran_ue); - ogs_assert(ran_ue->deactivation.group); + if (ran_ue) { + ogs_assert(ran_ue->deactivation.group); - r = ngap_send_ran_ue_context_release_command(ran_ue, - ran_ue->deactivation.group, - ran_ue->deactivation.cause, - NGAP_UE_CTX_REL_NG_REMOVE_AND_UNLINK, 0); - ogs_expect(r == OGS_OK); - ogs_assert(r != OGS_ERROR); + r = ngap_send_ran_ue_context_release_command(ran_ue, + ran_ue->deactivation.group, + ran_ue->deactivation.cause, + NGAP_UE_CTX_REL_NG_REMOVE_AND_UNLINK, 0); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + } else { + ogs_warn("[%s] RAN-NG Context has already been removed", + amf_ue->supi); + } } else if (state == AMF_UPDATE_SM_CONTEXT_MODIFIED) { /* @@ -625,15 +629,19 @@ int amf_nsmf_pdusession_handle_update_sm_context( */ if (AMF_SESSION_SYNC_DONE(amf_ue, state)) { - ogs_assert(ran_ue); - ogs_assert(ran_ue->deactivation.group); + if (ran_ue) { + ogs_assert(ran_ue->deactivation.group); - r = ngap_send_ran_ue_context_release_command(ran_ue, - ran_ue->deactivation.group, - ran_ue->deactivation.cause, - NGAP_UE_CTX_REL_NG_REMOVE_AND_UNLINK, 0); - ogs_expect(r == OGS_OK); - ogs_assert(r != OGS_ERROR); + r = ngap_send_ran_ue_context_release_command(ran_ue, + ran_ue->deactivation.group, + ran_ue->deactivation.cause, + NGAP_UE_CTX_REL_NG_REMOVE_AND_UNLINK, 0); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + } else { + ogs_warn("[%s] RAN-NG Context has already been removed", + amf_ue->supi); + } } } else if (state == AMF_UPDATE_SM_CONTEXT_REGISTRATION_REQUEST) { From 3b53144ca50c8738ce9a653069330ce37de74f8e Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Mon, 5 May 2025 22:05:34 +0900 Subject: [PATCH 14/22] [AMF/MME] default to Non-GBR flow when MBR/GBR parameters are missing (#3858) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace hard assertions on MBR/GBR presence in S1AP e‐RAB setup with a runtime check: if any of the four parameters (MBR DL/UL, GBR DL/UL) is missing, log an error and treat the bearer as Non-GBR - Mirror the same logic in SMF’s NGAP build routines for PDU Session Resource Setup and Modify transfers: drop the assertions, emit detailed error messages with the missing MBR/GBR values, and omit GBR IEs - Ensures graceful handling of incomplete QoS configurations by defaulting to best‐effort (Non-GBR) rather than crashing --- src/mme/s1ap-build.c | 91 ++++++++++++++++++++++++++------------------ src/smf/ngap-build.c | 78 +++++++++++++++++++++++-------------- 2 files changed, 104 insertions(+), 65 deletions(-) diff --git a/src/mme/s1ap-build.c b/src/mme/s1ap-build.c index 012cf716f..3a0d609f3 100644 --- a/src/mme/s1ap-build.c +++ b/src/mme/s1ap-build.c @@ -372,30 +372,39 @@ static void fill_e_rab_to_be_setup( if (bearer->qos.mbr.downlink || bearer->qos.mbr.uplink || bearer->qos.gbr.downlink || bearer->qos.gbr.uplink) { - ogs_assert(bearer->qos.mbr.downlink); - ogs_assert(bearer->qos.mbr.uplink); - ogs_assert(bearer->qos.gbr.downlink); - ogs_assert(bearer->qos.gbr.uplink); + if (bearer->qos.mbr.downlink && bearer->qos.mbr.uplink && + bearer->qos.gbr.downlink && bearer->qos.gbr.uplink) { - ogs_debug(" MBR[DL:%lld,UL:%lld]", - (long long)bearer->qos.mbr.downlink, - (long long)bearer->qos.mbr.uplink); - ogs_debug(" GBR[DL:%lld,UL:%lld]", - (long long)bearer->qos.gbr.downlink, - (long long)bearer->qos.gbr.uplink); + ogs_debug(" MBR[DL:%lld,UL:%lld]", + (long long)bearer->qos.mbr.downlink, + (long long)bearer->qos.mbr.uplink); + ogs_debug(" GBR[DL:%lld,UL:%lld]", + (long long)bearer->qos.gbr.downlink, + (long long)bearer->qos.gbr.uplink); - gbrQosInformation = - CALLOC(1, sizeof(struct S1AP_GBR_QosInformation)); - asn_uint642INTEGER(&gbrQosInformation->e_RAB_MaximumBitrateDL, - bearer->qos.mbr.downlink); - asn_uint642INTEGER(&gbrQosInformation->e_RAB_MaximumBitrateUL, - bearer->qos.mbr.uplink); - asn_uint642INTEGER(&gbrQosInformation-> - e_RAB_GuaranteedBitrateDL, bearer->qos.gbr.downlink); - asn_uint642INTEGER(&gbrQosInformation-> - e_RAB_GuaranteedBitrateUL, bearer->qos.gbr.uplink); - e_rab->e_RABlevelQoSParameters.gbrQosInformation = - gbrQosInformation; + gbrQosInformation = + CALLOC(1, sizeof(struct S1AP_GBR_QosInformation)); + asn_uint642INTEGER(&gbrQosInformation->e_RAB_MaximumBitrateDL, + bearer->qos.mbr.downlink); + asn_uint642INTEGER(&gbrQosInformation->e_RAB_MaximumBitrateUL, + bearer->qos.mbr.uplink); + asn_uint642INTEGER(&gbrQosInformation-> + e_RAB_GuaranteedBitrateDL, bearer->qos.gbr.downlink); + asn_uint642INTEGER(&gbrQosInformation-> + e_RAB_GuaranteedBitrateUL, bearer->qos.gbr.uplink); + e_rab->e_RABlevelQoSParameters.gbrQosInformation = + gbrQosInformation; + + } else { + ogs_error("Missing one or more MBR/GBR parameters; " + "defaulting to Non-GBR flow "); + ogs_error(" MBR[DL:%lld,UL:%lld]", + (long long)bearer->qos.mbr.downlink, + (long long)bearer->qos.mbr.uplink); + ogs_error(" GBR[DL:%lld,UL:%lld]", + (long long)bearer->qos.gbr.downlink, + (long long)bearer->qos.gbr.uplink); + } } rv = ogs_asn_ip_to_BIT_STRING( @@ -1141,21 +1150,31 @@ ogs_pkbuf_t *s1ap_build_e_rab_setup_request( if (bearer->qos.mbr.downlink || bearer->qos.mbr.uplink || bearer->qos.gbr.downlink || bearer->qos.gbr.uplink) { - ogs_assert(bearer->qos.mbr.downlink); - ogs_assert(bearer->qos.mbr.uplink); - ogs_assert(bearer->qos.gbr.downlink); - ogs_assert(bearer->qos.gbr.uplink); + if (bearer->qos.mbr.downlink && bearer->qos.mbr.uplink && + bearer->qos.gbr.downlink && bearer->qos.gbr.uplink) { - gbrQosInformation = CALLOC(1, sizeof(S1AP_GBR_QosInformation_t)); - asn_uint642INTEGER(&gbrQosInformation->e_RAB_MaximumBitrateDL, - bearer->qos.mbr.downlink); - asn_uint642INTEGER(&gbrQosInformation->e_RAB_MaximumBitrateUL, - bearer->qos.mbr.uplink); - asn_uint642INTEGER(&gbrQosInformation->e_RAB_GuaranteedBitrateDL, - bearer->qos.gbr.downlink); - asn_uint642INTEGER(&gbrQosInformation->e_RAB_GuaranteedBitrateUL, - bearer->qos.gbr.uplink); - e_rab->e_RABlevelQoSParameters.gbrQosInformation = gbrQosInformation; + gbrQosInformation = CALLOC(1, sizeof(S1AP_GBR_QosInformation_t)); + asn_uint642INTEGER(&gbrQosInformation->e_RAB_MaximumBitrateDL, + bearer->qos.mbr.downlink); + asn_uint642INTEGER(&gbrQosInformation->e_RAB_MaximumBitrateUL, + bearer->qos.mbr.uplink); + asn_uint642INTEGER(&gbrQosInformation->e_RAB_GuaranteedBitrateDL, + bearer->qos.gbr.downlink); + asn_uint642INTEGER(&gbrQosInformation->e_RAB_GuaranteedBitrateUL, + bearer->qos.gbr.uplink); + e_rab->e_RABlevelQoSParameters.gbrQosInformation = + gbrQosInformation; + + } else { + ogs_error("Missing one or more MBR/GBR parameters; " + "defaulting to Non-GBR flow "); + ogs_error(" MBR[DL:%lld,UL:%lld]", + (long long)bearer->qos.mbr.downlink, + (long long)bearer->qos.mbr.uplink); + ogs_error(" GBR[DL:%lld,UL:%lld]", + (long long)bearer->qos.gbr.downlink, + (long long)bearer->qos.gbr.uplink); + } } rv = ogs_asn_ip_to_BIT_STRING( diff --git a/src/smf/ngap-build.c b/src/smf/ngap-build.c index 75c2bd342..946f1aca2 100644 --- a/src/smf/ngap-build.c +++ b/src/smf/ngap-build.c @@ -260,23 +260,33 @@ ogs_pkbuf_t *ngap_build_pdu_session_resource_setup_request_transfer( if (qos_flow->qos.mbr.downlink || qos_flow->qos.mbr.uplink || qos_flow->qos.gbr.downlink || qos_flow->qos.gbr.uplink) { - ogs_assert(qos_flow->qos.mbr.downlink); - ogs_assert(qos_flow->qos.mbr.uplink); - ogs_assert(qos_flow->qos.gbr.downlink); - ogs_assert(qos_flow->qos.gbr.uplink); - qosFlowLevelQosParameters->gBR_QosInformation = - gBR_QosInformation = CALLOC(1, sizeof(*gBR_QosInformation)); - ogs_assert(gBR_QosInformation); + if (qos_flow->qos.mbr.downlink && qos_flow->qos.mbr.uplink && + qos_flow->qos.gbr.downlink && qos_flow->qos.gbr.uplink) { - asn_uint642INTEGER(&gBR_QosInformation->maximumFlowBitRateDL, - qos_flow->qos.mbr.downlink); - asn_uint642INTEGER(&gBR_QosInformation->maximumFlowBitRateUL, - qos_flow->qos.mbr.uplink); - asn_uint642INTEGER(&gBR_QosInformation-> - guaranteedFlowBitRateDL, qos_flow->qos.gbr.downlink); - asn_uint642INTEGER(&gBR_QosInformation-> - guaranteedFlowBitRateUL, qos_flow->qos.gbr.uplink); + qosFlowLevelQosParameters->gBR_QosInformation = + gBR_QosInformation = CALLOC(1, sizeof(*gBR_QosInformation)); + ogs_assert(gBR_QosInformation); + + asn_uint642INTEGER(&gBR_QosInformation->maximumFlowBitRateDL, + qos_flow->qos.mbr.downlink); + asn_uint642INTEGER(&gBR_QosInformation->maximumFlowBitRateUL, + qos_flow->qos.mbr.uplink); + asn_uint642INTEGER(&gBR_QosInformation-> + guaranteedFlowBitRateDL, qos_flow->qos.gbr.downlink); + asn_uint642INTEGER(&gBR_QosInformation-> + guaranteedFlowBitRateUL, qos_flow->qos.gbr.uplink); + + } else { + ogs_error("Missing one or more MBR/GBR parameters; " + "defaulting to Non-GBR flow "); + ogs_error(" MBR[DL:%lld,UL:%lld]", + (long long)qos_flow->qos.mbr.downlink, + (long long)qos_flow->qos.mbr.uplink); + ogs_error(" GBR[DL:%lld,UL:%lld]", + (long long)qos_flow->qos.gbr.downlink, + (long long)qos_flow->qos.gbr.uplink); + } } } @@ -355,22 +365,32 @@ ogs_pkbuf_t *ngap_build_pdu_session_resource_modify_request_transfer( if (qos_presence == true && (qos_flow->qos.mbr.downlink || qos_flow->qos.mbr.uplink || qos_flow->qos.gbr.downlink || qos_flow->qos.gbr.uplink)) { - ogs_assert(qos_flow->qos.mbr.downlink); - ogs_assert(qos_flow->qos.mbr.uplink); - ogs_assert(qos_flow->qos.gbr.downlink); - ogs_assert(qos_flow->qos.gbr.uplink); - qosFlowLevelQosParameters->gBR_QosInformation = - gBR_QosInformation = CALLOC(1, sizeof(*gBR_QosInformation)); + if (qos_flow->qos.mbr.downlink && qos_flow->qos.mbr.uplink && + qos_flow->qos.gbr.downlink && qos_flow->qos.gbr.uplink) { - asn_uint642INTEGER(&gBR_QosInformation->maximumFlowBitRateDL, - qos_flow->qos.mbr.downlink); - asn_uint642INTEGER(&gBR_QosInformation->maximumFlowBitRateUL, - qos_flow->qos.mbr.uplink); - asn_uint642INTEGER(&gBR_QosInformation-> - guaranteedFlowBitRateDL, qos_flow->qos.gbr.downlink); - asn_uint642INTEGER(&gBR_QosInformation-> - guaranteedFlowBitRateUL, qos_flow->qos.gbr.uplink); + qosFlowLevelQosParameters->gBR_QosInformation = + gBR_QosInformation = CALLOC(1, sizeof(*gBR_QosInformation)); + + asn_uint642INTEGER(&gBR_QosInformation->maximumFlowBitRateDL, + qos_flow->qos.mbr.downlink); + asn_uint642INTEGER(&gBR_QosInformation->maximumFlowBitRateUL, + qos_flow->qos.mbr.uplink); + asn_uint642INTEGER(&gBR_QosInformation-> + guaranteedFlowBitRateDL, qos_flow->qos.gbr.downlink); + asn_uint642INTEGER(&gBR_QosInformation-> + guaranteedFlowBitRateUL, qos_flow->qos.gbr.uplink); + + } else { + ogs_error("Missing one or more MBR/GBR parameters; " + "defaulting to Non-GBR flow "); + ogs_error(" MBR[DL:%lld,UL:%lld]", + (long long)qos_flow->qos.mbr.downlink, + (long long)qos_flow->qos.mbr.uplink); + ogs_error(" GBR[DL:%lld,UL:%lld]", + (long long)qos_flow->qos.gbr.downlink, + (long long)qos_flow->qos.gbr.uplink); + } } } From aab6940cd5c8798f24558829e656d9064e747a8a Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Tue, 6 May 2025 15:47:17 +0900 Subject: [PATCH 15/22] [AMF] improve HTTP/2 timeout handling and error logging (#3862, #3863) - Check ran_ue existence and abort if NG context has already been removed - Detect deassociated RAN-UE (invalid amf_ue_id) and break to avoid further processing - Validate AMF-UE ID matches ran_ue->amf_ue_id and skip on mismatch --- lib/sbi/context.c | 6 +++++- lib/sbi/context.h | 29 +++++++++++++++++++++++++++++ src/amf/amf-sm.c | 31 ++++++++++++++++++++++++++++--- src/amf/context.h | 3 +++ src/amf/ngap-build.c | 8 +++++++- src/smf/smf-sm.c | 21 +++++++++++++++++++-- 6 files changed, 91 insertions(+), 7 deletions(-) diff --git a/lib/sbi/context.c b/lib/sbi/context.c index a57d56c80..2873fe288 100644 --- a/lib/sbi/context.c +++ b/lib/sbi/context.c @@ -2433,8 +2433,12 @@ void ogs_sbi_object_free(ogs_sbi_object_t *sbi_object) ogs_assert(sbi_object); - if (ogs_list_count(&sbi_object->xact_list)) + if (ogs_list_count(&sbi_object->xact_list)) { + ogs_sbi_xact_t *xact = NULL; \ ogs_error("SBI running [%d]", ogs_list_count(&sbi_object->xact_list)); + ogs_list_for_each(&sbi_object->xact_list, xact) + OGS_SBI_XACT_LOG(xact); + } for (i = 0; i < OGS_SBI_MAX_NUM_OF_SERVICE_TYPE; i++) { if (sbi_object->service_type_array[i].nf_instance_id) diff --git a/lib/sbi/context.h b/lib/sbi/context.h index 70aec9007..b71706791 100644 --- a/lib/sbi/context.h +++ b/lib/sbi/context.h @@ -225,6 +225,35 @@ typedef struct ogs_sbi_object_s { typedef ogs_sbi_request_t *(*ogs_sbi_build_f)( void *context, void *data); +#define OGS_SBI_XACT_LOG(xact) \ + do { \ + ogs_error(" requester-nf-type[%s:%d]", \ + OpenAPI_nf_type_ToString((xact)->requester_nf_type), \ + (xact)->requester_nf_type); \ + ogs_error(" service-name[%s:%d]", \ + ogs_sbi_service_type_to_name((xact)->service_type), \ + (xact)->service_type); \ + if ((xact)->request) { \ + int i; \ + ogs_sbi_request_t *request = (xact)->request; \ + if (request->h.method) \ + ogs_error(" h.method[%s]", request->h.method); \ + if (request->h.uri) \ + ogs_error(" h.uri[%s]", request->h.uri); \ + if (request->h.service.name) \ + ogs_error(" h.service.name[%s]", request->h.service.name); \ + if (request->h.api.version) \ + ogs_error(" h.api.version[%s]", request->h.api.version); \ + for (i = 0; i < OGS_SBI_MAX_NUM_OF_RESOURCE_COMPONENT && \ + request->h.resource.component[i]; i++) \ + ogs_error(" h.resource.component[%s:%d]", \ + request->h.resource.component[i], i); \ + ogs_error(" http.content_length[%d]", \ + (int)request->http.content_length); \ + if (request->http.content) \ + ogs_error(" http.content[%s]", request->http.content); \ + } \ + } while(0) typedef struct ogs_sbi_xact_s { ogs_lnode_t lnode; diff --git a/src/amf/amf-sm.c b/src/amf/amf-sm.c index f47ab4b4f..8aa8bc197 100644 --- a/src/amf/amf-sm.c +++ b/src/amf/amf-sm.c @@ -751,7 +751,9 @@ void amf_state_operational(ogs_fsm_t *s, amf_event_t *e) break; } - ogs_error("[%s] Cannot receive SBI message", amf_ue->suci); + ogs_error("[%s:%s] Cannot receive SBI message", + amf_ue->supi, amf_ue->suci); + r = nas_5gs_send_gmm_reject_from_sbi(amf_ue, OGS_SBI_HTTP_STATUS_GATEWAY_TIMEOUT); ogs_expect(r == OGS_OK); @@ -771,8 +773,31 @@ void amf_state_operational(ogs_fsm_t *s, amf_event_t *e) break; } - ogs_error("[%d:%d] Cannot receive SBI message", - sess->psi, sess->pti); + ogs_error("[%s:%s:%d:%d] Cannot receive SBI message", + amf_ue->supi, amf_ue->suci, sess->psi, sess->pti); + + ran_ue = ran_ue_find_by_id(sess->ran_ue_id); + if (!ran_ue) { + ogs_error("[%s:%s:%d:%d] " + "NG Context has already been removed", + amf_ue->supi, amf_ue->suci, sess->psi, sess->pti); + break; + } + + if (ran_ue->amf_ue_id == OGS_INVALID_POOL_ID) { + ogs_error("[%s:%s:%d:%d] " + "RAN-UE has already been deassociated", + amf_ue->supi, amf_ue->suci, sess->psi, sess->pti); + break; + } + + if (amf_ue->id != ran_ue->amf_ue_id) { + ogs_error("[%s:%s:%d:%d] AMF-UE mismatched [%d!=%d]", + amf_ue->supi, amf_ue->suci, sess->psi, sess->pti, + amf_ue->id, ran_ue->amf_ue_id); + break; + } + if (sess->payload_container_type) { r = nas_5gs_send_back_gsm_message( ran_ue_find_by_id(sess->ran_ue_id), sess, diff --git a/src/amf/context.h b/src/amf/context.h index 6441449e8..7aff61206 100644 --- a/src/amf/context.h +++ b/src/amf/context.h @@ -1033,8 +1033,11 @@ amf_sess_t *amf_sess_add(amf_ue_t *amf_ue, uint8_t psi); ogs_assert(sbi_object); \ \ if (ogs_list_count(&sbi_object->xact_list)) { \ + ogs_sbi_xact_t *xact = NULL; \ ogs_error("SBI running [%d]", \ ogs_list_count(&sbi_object->xact_list)); \ + ogs_list_for_each(&sbi_object->xact_list, xact) \ + OGS_SBI_XACT_LOG(xact); \ } else { \ amf_sess_remove(__sESS); \ } \ diff --git a/src/amf/ngap-build.c b/src/amf/ngap-build.c index d84b3b897..0c4f6f72c 100644 --- a/src/amf/ngap-build.c +++ b/src/amf/ngap-build.c @@ -315,7 +315,13 @@ ogs_pkbuf_t *ngap_build_downlink_nas_transport( ogs_assert(gmmbuf); ogs_assert(ran_ue); amf_ue = amf_ue_find_by_id(ran_ue->amf_ue_id); - ogs_assert(amf_ue); + if (!amf_ue) { + ogs_fatal(" AMF-UE-ID[%d] RAN_UE_NGAP_ID[%lld] AMF_UE_NGAP_ID[%lld]", + ran_ue->amf_ue_id, + (long long)ran_ue->ran_ue_ngap_id, + (long long)ran_ue->amf_ue_ngap_id); + ogs_assert_if_reached(); + } ogs_debug("DownlinkNASTransport"); diff --git a/src/smf/smf-sm.c b/src/smf/smf-sm.c index 4c161de1b..df40591b0 100644 --- a/src/smf/smf-sm.c +++ b/src/smf/smf-sm.c @@ -80,6 +80,7 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) ogs_sbi_message_t sbi_message; ogs_sbi_xact_t *sbi_xact = NULL; ogs_pool_id_t sbi_xact_id = OGS_INVALID_POOL_ID; + ogs_sbi_object_t *sbi_object = NULL; ogs_pool_id_t sbi_object_id = OGS_INVALID_POOL_ID; ogs_nas_5gs_message_t nas_message; @@ -1040,14 +1041,30 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) /* Here, we should not use ogs_assert(stream) * since 'namf-comm' service has no an associated stream. */ + sbi_object = sbi_xact->sbi_object; + ogs_assert(sbi_object); + + sbi_object_id = sbi_xact->sbi_object_id; + ogs_assert(sbi_object_id >= OGS_MIN_POOL_ID && + sbi_object_id <= OGS_MAX_POOL_ID); + ogs_sbi_xact_remove(sbi_xact); - ogs_error("Cannot receive SBI message"); + sess = smf_sess_find_by_id(sbi_object_id); + if (!sess) { + ogs_error("Session has already been removed"); + break; + } + smf_ue = smf_ue_find_by_id(sess->smf_ue_id); + ogs_assert(smf_ue); + + ogs_error("[%s:%d] Cannot receive SBI message", + smf_ue->supi, sess->psi); if (stream) { ogs_assert(true == ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_GATEWAY_TIMEOUT, NULL, - "Cannot receive SBI message", NULL, NULL)); + "Cannot receive SBI message", smf_ue->supi, NULL)); } break; From 62cb99755243c9c38e4c060c5d8d0e158fe8cdd5 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Tue, 6 May 2025 16:28:48 +0900 Subject: [PATCH 16/22] [AMF/MME] Modify common_register_state to handle missing UE contexts gracefully (#3874) Previously, both AMF and MME assumed that RAN UE contexts would always be present, triggering fatal assertions when a context lookup failed. This change introduces explicit checks in the common_register_state handlers to detect missing NG and S1 contexts without crashing: --- src/amf/gmm-sm.c | 10 ++++++++++ src/mme/emm-sm.c | 6 +++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/amf/gmm-sm.c b/src/amf/gmm-sm.c index 3c734d21f..e7cacf05c 100644 --- a/src/amf/gmm-sm.c +++ b/src/amf/gmm-sm.c @@ -1313,6 +1313,16 @@ static void common_register_state(ogs_fsm_t *s, amf_event_t *e, ran_ue = ran_ue_find_by_id(amf_ue->ran_ue_id); ogs_assert(ran_ue); + ran_ue = ran_ue_find_by_id(amf_ue->ran_ue_id); + if (!ran_ue) { + ogs_error("No NG Context SUPI[%s] NAS-Type[%d] " + "RAN-UE-ID[%d:%p]", + amf_ue->supi, nas_message->gmm.h.message_type, + amf_ue->ran_ue_id, ran_ue_find_by_id(amf_ue->ran_ue_id)); + ogs_assert(e->pkbuf); + ogs_log_hexdump(OGS_LOG_ERROR, e->pkbuf->data, e->pkbuf->len); + break; + } h.type = e->nas.type; diff --git a/src/mme/emm-sm.c b/src/mme/emm-sm.c index 94fd2e78d..725bdcb3c 100644 --- a/src/mme/emm-sm.c +++ b/src/mme/emm-sm.c @@ -337,15 +337,15 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e, enb_ue = enb_ue_find_by_id(mme_ue->enb_ue_id); if (!enb_ue) { - ogs_fatal("No S1 Context IMSI[%s] NAS-Type[%d] " + ogs_error("No S1 Context IMSI[%s] NAS-Type[%d] " "ENB-UE-ID[%d:%d][%p:%p]", mme_ue->imsi_bcd, message->emm.h.message_type, e->enb_ue_id, mme_ue->enb_ue_id, enb_ue_find_by_id(e->enb_ue_id), enb_ue_find_by_id(mme_ue->enb_ue_id)); ogs_assert(e->pkbuf); - ogs_log_hexdump(OGS_LOG_FATAL, e->pkbuf->data, e->pkbuf->len); - ogs_assert_if_reached(); + ogs_log_hexdump(OGS_LOG_ERROR, e->pkbuf->data, e->pkbuf->len); + break; } h.type = e->nas_type; From cfa44575020f3fb045fd971358442053c8684d3d Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Tue, 6 May 2025 17:52:51 +0900 Subject: [PATCH 17/22] [AMF/MME] Remove fatal assertions on oversized SCTP messages in NGAP and S1AP handlers (#3878) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, any SCTP recv would trigger ogs_fatal and an assert_if_reached when MSG_EOR wasn’t set, causing the AMF or MME to crash on oversized or fragmented packets. Since we rely on a 32 KB receive buffer and do not support SCTP reassembly, this change replaces the conditional fatal/assert logic with a single ogs_error call in both ngap_recv_handler and s1ap_recv_handler. Oversized or partial SCTP messages are now logged and dropped instead of crashing the process. --- src/amf/ngap-sctp.c | 10 ++-------- src/mme/s1ap-sctp.c | 10 ++-------- src/mme/sgsap-sctp.c | 10 ++-------- 3 files changed, 6 insertions(+), 24 deletions(-) diff --git a/src/amf/ngap-sctp.c b/src/amf/ngap-sctp.c index e7e8a8b7a..4dada4ef3 100644 --- a/src/amf/ngap-sctp.c +++ b/src/amf/ngap-sctp.c @@ -243,14 +243,8 @@ void ngap_recv_handler(ogs_sock_t *sock) ngap_event_push(AMF_EVENT_NGAP_MESSAGE, sock, addr, pkbuf, 0, 0); return; } else { - if (ogs_socket_errno != OGS_EAGAIN) { - ogs_fatal("ogs_sctp_recvmsg(%d) failed(%d:%s-0x%x)", - size, errno, strerror(errno), flags); - ogs_assert_if_reached(); - } else { - ogs_error("ogs_sctp_recvmsg(%d) failed(%d:%s-0x%x)", - size, errno, strerror(errno), flags); - } + ogs_error("ogs_sctp_recvmsg(%d) failed(%d:%s-0x%x)", + size, errno, strerror(errno), flags); } ogs_pkbuf_free(pkbuf); diff --git a/src/mme/s1ap-sctp.c b/src/mme/s1ap-sctp.c index 5e08c62ea..b1626e717 100644 --- a/src/mme/s1ap-sctp.c +++ b/src/mme/s1ap-sctp.c @@ -245,14 +245,8 @@ void s1ap_recv_handler(ogs_sock_t *sock) s1ap_event_push(MME_EVENT_S1AP_MESSAGE, sock, addr, pkbuf, 0, 0); return; } else { - if (ogs_socket_errno != OGS_EAGAIN) { - ogs_fatal("ogs_sctp_recvmsg(%d) failed(%d:%s-0x%x)", - size, errno, strerror(errno), flags); - ogs_assert_if_reached(); - } else { - ogs_error("ogs_sctp_recvmsg(%d) failed(%d:%s-0x%x)", - size, errno, strerror(errno), flags); - } + ogs_error("ogs_sctp_recvmsg(%d) failed(%d:%s-0x%x)", + size, errno, strerror(errno), flags); } ogs_pkbuf_free(pkbuf); diff --git a/src/mme/sgsap-sctp.c b/src/mme/sgsap-sctp.c index c262a848c..18fc354cd 100644 --- a/src/mme/sgsap-sctp.c +++ b/src/mme/sgsap-sctp.c @@ -183,14 +183,8 @@ static void recv_handler(ogs_sock_t *sock) sgsap_event_push(MME_EVENT_SGSAP_MESSAGE, sock, NULL, pkbuf, 0, 0); return; } else { - if (ogs_socket_errno != OGS_EAGAIN) { - ogs_fatal("ogs_sctp_recvmsg(%d) failed(%d:%s-0x%x)", - size, errno, strerror(errno), flags); - ogs_assert_if_reached(); - } else { - ogs_error("ogs_sctp_recvmsg(%d) failed(%d:%s-0x%x)", - size, errno, strerror(errno), flags); - } + ogs_error("ogs_sctp_recvmsg(%d) failed(%d:%s-0x%x)", + size, errno, strerror(errno), flags); } ogs_pkbuf_free(pkbuf); } From a82a63bb1f88047bd42448a113c93f8e6075ebf4 Mon Sep 17 00:00:00 2001 From: Spencer Sevilla Date: Tue, 6 May 2025 16:10:13 -0700 Subject: [PATCH 18/22] need to NULL out poll/sock pointers to prevent mme crash on vlr detach --- src/mme/mme-context.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/mme/mme-context.c b/src/mme/mme-context.c index ca26836d2..0590233c0 100644 --- a/src/mme/mme-context.c +++ b/src/mme/mme-context.c @@ -2838,10 +2838,14 @@ void mme_vlr_close(mme_vlr_t *vlr) { ogs_assert(vlr); - if (vlr->poll) + if (vlr->poll) { ogs_pollset_remove(vlr->poll); - if (vlr->sock) + vlr->poll = NULL; + } + if (vlr->sock) { ogs_sctp_destroy(vlr->sock); + vlr->sock = NULL; + } } mme_vlr_t *mme_vlr_find_by_sock(const ogs_sock_t *sock) From 8e286b67f1ccdd1d6bc31d36b553991337583f33 Mon Sep 17 00:00:00 2001 From: herlesupreeth Date: Sun, 4 May 2025 01:03:42 +0200 Subject: [PATCH 19/22] [PCF] Add AF in list of allowed NF types for PCF --- src/pcf/sbi-path.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/pcf/sbi-path.c b/src/pcf/sbi-path.c index 4d358e45e..758e5f91a 100644 --- a/src/pcf/sbi-path.c +++ b/src/pcf/sbi-path.c @@ -37,6 +37,7 @@ int pcf_sbi_open(void) ogs_sbi_nf_instance_add_allowed_nf_type(nf_instance, OpenAPI_nf_type_SCP); ogs_sbi_nf_instance_add_allowed_nf_type(nf_instance, OpenAPI_nf_type_AMF); ogs_sbi_nf_instance_add_allowed_nf_type(nf_instance, OpenAPI_nf_type_SMF); + ogs_sbi_nf_instance_add_allowed_nf_type(nf_instance, OpenAPI_nf_type_AF); /* Build NF service information. It will be transmitted to NRF. */ if (ogs_sbi_nf_service_is_available( @@ -68,6 +69,8 @@ int pcf_sbi_open(void) ogs_assert(service); ogs_sbi_nf_service_add_version( service, OGS_SBI_API_V1, OGS_SBI_API_V1_0_0, NULL); + ogs_sbi_nf_service_add_allowed_nf_type(service, OpenAPI_nf_type_AF); + ogs_sbi_nf_service_add_allowed_nf_type(service, OpenAPI_nf_type_PCF); policyauthorization_enabled = true; } From 9ce109a9e18df1546c868efc8a33f600eec3644e Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Fri, 9 May 2025 15:10:23 +0900 Subject: [PATCH 20/22] [PCF] split PCF_UE context into distinct AM and SM contexts (#3868) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Separate the monolithic PCF_UE structure into PCF_UE_AM and PCF_UE_SM to fully decouple AM‐ and SM‐policy lifecycles. --- src/bsf/bsf-sm.c | 3 +- src/pcf/am-sm.c | 50 +++++---- src/pcf/context.c | 232 +++++++++++++++++++++++++++-------------- src/pcf/context.h | 62 ++++++++--- src/pcf/event.h | 8 +- src/pcf/namf-build.c | 10 +- src/pcf/namf-build.h | 4 +- src/pcf/nbsf-build.c | 18 ++-- src/pcf/nbsf-handler.c | 24 ++--- src/pcf/nnrf-handler.c | 16 +-- src/pcf/npcf-handler.c | 214 +++++++++++++++++++------------------ src/pcf/npcf-handler.h | 4 +- src/pcf/nudr-build.c | 16 +-- src/pcf/nudr-build.h | 4 +- src/pcf/nudr-handler.c | 53 +++++----- src/pcf/nudr-handler.h | 5 +- src/pcf/pcf-sm.c | 145 +++++++++++++------------- src/pcf/sbi-path.c | 45 ++++---- src/pcf/sbi-path.h | 10 +- src/pcf/sm-sm.c | 120 +++++++++++---------- src/smf/context.c | 3 + src/smf/context.h | 3 + src/smf/npcf-build.c | 5 +- src/smf/nsmf-handler.c | 4 + 24 files changed, 604 insertions(+), 454 deletions(-) diff --git a/src/bsf/bsf-sm.c b/src/bsf/bsf-sm.c index fff9f4ccd..f0ea09005 100644 --- a/src/bsf/bsf-sm.c +++ b/src/bsf/bsf-sm.c @@ -172,7 +172,8 @@ void bsf_state_operational(ogs_fsm_t *s, bsf_event_t *e) } if (!sess) { - ogs_error("Not found [%s]", message.h.uri); + ogs_error("Not found [%s:%s]", + message.h.method, message.h.uri); ogs_assert(true == ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_NOT_FOUND, diff --git a/src/pcf/am-sm.c b/src/pcf/am-sm.c index 289abadb3..e4f4dbc45 100644 --- a/src/pcf/am-sm.c +++ b/src/pcf/am-sm.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019-2024 by Sukchan Lee + * Copyright (C) 2019-2025 by Sukchan Lee * * This file is part of Open5GS. * @@ -37,7 +37,7 @@ void pcf_am_state_final(ogs_fsm_t *s, pcf_event_t *e) void pcf_am_state_operational(ogs_fsm_t *s, pcf_event_t *e) { bool handled; - pcf_ue_t *pcf_ue = NULL; + pcf_ue_am_t *pcf_ue_am = NULL; ogs_sbi_stream_t *stream = NULL; ogs_pool_id_t stream_id; @@ -48,8 +48,8 @@ void pcf_am_state_operational(ogs_fsm_t *s, pcf_event_t *e) pcf_sm_debug(e); - pcf_ue = pcf_ue_find_by_id(e->pcf_ue_id); - ogs_assert(pcf_ue); + pcf_ue_am = pcf_ue_am_find_by_id(e->pcf_ue_am_id); + ogs_assert(pcf_ue_am); switch (e->h.id) { case OGS_FSM_ENTRY_SIG: @@ -75,9 +75,9 @@ void pcf_am_state_operational(ogs_fsm_t *s, pcf_event_t *e) SWITCH(message->h.method) CASE(OGS_SBI_HTTP_METHOD_POST) handled = pcf_npcf_am_policy_control_handle_create( - pcf_ue, stream, message); + pcf_ue_am, stream, message); if (!handled) { - ogs_error("[%s] Cannot handle SBI message", pcf_ue->supi); + ogs_error("[%s] Cannot handle SBI message", pcf_ue_am->supi); OGS_FSM_TRAN(s, pcf_am_state_exception); } break; @@ -89,7 +89,7 @@ void pcf_am_state_operational(ogs_fsm_t *s, pcf_event_t *e) DEFAULT ogs_error("[%s] Invalid HTTP method [%s]", - pcf_ue->supi, message->h.method); + pcf_ue_am->supi, message->h.method); ogs_assert(true == ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_METHOD_NOT_ALLOWED, message, @@ -122,39 +122,40 @@ void pcf_am_state_operational(ogs_fsm_t *s, pcf_event_t *e) if (message->res_status == OGS_SBI_HTTP_STATUS_NOT_FOUND) { ogs_warn("[%s] Cannot find SUPI [%d]", - pcf_ue->supi, message->res_status); + pcf_ue_am->supi, message->res_status); } else { ogs_error("[%s] HTTP response error [%d]", - pcf_ue->supi, message->res_status); + pcf_ue_am->supi, message->res_status); } ogs_assert(true == ogs_sbi_server_send_error( stream, message->res_status, - NULL, "HTTP response error", pcf_ue->supi, + NULL, "HTTP response error", pcf_ue_am->supi, NULL)); break; } - pcf_nudr_dr_handle_query_am_data(pcf_ue, stream, message); + pcf_nudr_dr_handle_query_am_data( + pcf_ue_am, stream, message); break; DEFAULT ogs_error("[%s] Invalid resource name [%s]", - pcf_ue->supi, message->h.resource.component[1]); + pcf_ue_am->supi, message->h.resource.component[1]); ogs_assert_if_reached(); END break; DEFAULT ogs_error("[%s] Invalid resource name [%s]", - pcf_ue->supi, message->h.resource.component[0]); + pcf_ue_am->supi, message->h.resource.component[0]); ogs_assert_if_reached(); END break; DEFAULT ogs_error("[%s] Invalid API name [%s]", - pcf_ue->supi, message->h.service.name); + pcf_ue_am->supi, message->h.service.name); ogs_assert(true == ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, message, @@ -164,21 +165,22 @@ void pcf_am_state_operational(ogs_fsm_t *s, pcf_event_t *e) break; default: - ogs_error("[%s] Unknown event %s", pcf_ue->supi, pcf_event_get_name(e)); + ogs_error("[%s] Unknown event %s", + pcf_ue_am->supi, pcf_event_get_name(e)); break; } } void pcf_am_state_deleted(ogs_fsm_t *s, pcf_event_t *e) { - pcf_ue_t *pcf_ue = NULL; + pcf_ue_am_t *pcf_ue_am = NULL; ogs_assert(s); ogs_assert(e); pcf_sm_debug(e); - pcf_ue = pcf_ue_find_by_id(e->pcf_ue_id); - ogs_assert(pcf_ue); + pcf_ue_am = pcf_ue_am_find_by_id(e->pcf_ue_am_id); + ogs_assert(pcf_ue_am); switch (e->h.id) { case OGS_FSM_ENTRY_SIG: @@ -188,21 +190,22 @@ void pcf_am_state_deleted(ogs_fsm_t *s, pcf_event_t *e) break; default: - ogs_error("[%s] Unknown event %s", pcf_ue->supi, pcf_event_get_name(e)); + ogs_error("[%s] Unknown event %s", pcf_ue_am->supi, + pcf_event_get_name(e)); break; } } void pcf_am_state_exception(ogs_fsm_t *s, pcf_event_t *e) { - pcf_ue_t *pcf_ue = NULL; + pcf_ue_am_t *pcf_ue_am = NULL; ogs_assert(s); ogs_assert(e); pcf_sm_debug(e); - pcf_ue = pcf_ue_find_by_id(e->pcf_ue_id); - ogs_assert(pcf_ue); + pcf_ue_am = pcf_ue_am_find_by_id(e->pcf_ue_am_id); + ogs_assert(pcf_ue_am); switch (e->h.id) { case OGS_FSM_ENTRY_SIG: @@ -212,7 +215,8 @@ void pcf_am_state_exception(ogs_fsm_t *s, pcf_event_t *e) break; default: - ogs_error("[%s] Unknown event %s", pcf_ue->supi, pcf_event_get_name(e)); + ogs_error("[%s] Unknown event %s", pcf_ue_am->supi, + pcf_event_get_name(e)); break; } } diff --git a/src/pcf/context.c b/src/pcf/context.c index 67a6ed46a..8e9a5e290 100644 --- a/src/pcf/context.c +++ b/src/pcf/context.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019-2023 by Sukchan Lee + * Copyright (C) 2019-2025 by Sukchan Lee * * This file is part of Open5GS. * @@ -23,7 +23,8 @@ static pcf_context_t self; int __pcf_log_domain; -static OGS_POOL(pcf_ue_pool, pcf_ue_t); +static OGS_POOL(pcf_ue_am_pool, pcf_ue_am_t); +static OGS_POOL(pcf_ue_sm_pool, pcf_ue_sm_t); static OGS_POOL(pcf_sess_pool, pcf_sess_t); static OGS_POOL(pcf_app_pool, pcf_app_t); @@ -42,14 +43,18 @@ void pcf_context_init(void) ogs_log_install_domain(&__ogs_dbi_domain, "dbi", ogs_core()->log.level); ogs_log_install_domain(&__pcf_log_domain, "pcf", ogs_core()->log.level); - ogs_pool_init(&pcf_ue_pool, ogs_global_conf()->max.ue); + ogs_pool_init(&pcf_ue_am_pool, ogs_global_conf()->max.ue); + ogs_pool_init(&pcf_ue_sm_pool, ogs_global_conf()->max.ue); ogs_pool_init(&pcf_sess_pool, ogs_app()->pool.sess); ogs_pool_init(&pcf_app_pool, ogs_app()->pool.sess); - ogs_list_init(&self.pcf_ue_list); + ogs_list_init(&self.pcf_ue_am_list); + ogs_list_init(&self.pcf_ue_sm_list); - self.supi_hash = ogs_hash_make(); - ogs_assert(self.supi_hash); + self.supi_am_hash = ogs_hash_make(); + ogs_assert(self.supi_am_hash); + self.supi_sm_hash = ogs_hash_make(); + ogs_assert(self.supi_sm_hash); self.ipv4addr_hash = ogs_hash_make(); ogs_assert(self.ipv4addr_hash); self.ipv6prefix_hash = ogs_hash_make(); @@ -62,10 +67,13 @@ void pcf_context_final(void) { ogs_assert(context_initialized == 1); - pcf_ue_remove_all(); + pcf_ue_am_remove_all(); + pcf_ue_sm_remove_all(); - ogs_assert(self.supi_hash); - ogs_hash_destroy(self.supi_hash); + ogs_assert(self.supi_am_hash); + ogs_hash_destroy(self.supi_am_hash); + ogs_assert(self.supi_sm_hash); + ogs_hash_destroy(self.supi_sm_hash); ogs_assert(self.ipv4addr_hash); ogs_hash_destroy(self.ipv4addr_hash); ogs_assert(self.ipv6prefix_hash); @@ -73,7 +81,8 @@ void pcf_context_final(void) ogs_pool_final(&pcf_app_pool); ogs_pool_final(&pcf_sess_pool); - ogs_pool_final(&pcf_ue_pool); + ogs_pool_final(&pcf_ue_am_pool); + ogs_pool_final(&pcf_ue_sm_pool); context_initialized = 0; } @@ -335,110 +344,164 @@ int pcf_context_parse_config(void) return OGS_OK; } -pcf_ue_t *pcf_ue_add(char *supi) +pcf_ue_am_t *pcf_ue_am_add(char *supi) { pcf_event_t e; - pcf_ue_t *pcf_ue = NULL; + pcf_ue_am_t *pcf_ue_am = NULL; ogs_assert(supi); - ogs_pool_id_calloc(&pcf_ue_pool, &pcf_ue); - ogs_assert(pcf_ue); + ogs_pool_id_calloc(&pcf_ue_am_pool, &pcf_ue_am); + ogs_assert(pcf_ue_am); /* SBI Type */ - pcf_ue->sbi.type = OGS_SBI_OBJ_UE_TYPE; + pcf_ue_am->sbi.type = OGS_SBI_OBJ_UE_TYPE; /* SBI Features */ - OGS_SBI_FEATURES_SET(pcf_ue->am_policy_control_features, + OGS_SBI_FEATURES_SET(pcf_ue_am->am_policy_control_features, OGS_SBI_NPCF_AM_POLICY_CONTROL_UE_AMBR_AUTHORIZATION); - pcf_ue->association_id = ogs_msprintf("%d", - (int)ogs_pool_index(&pcf_ue_pool, pcf_ue)); - ogs_assert(pcf_ue->association_id); + pcf_ue_am->association_id = ogs_msprintf("%d", + (int)ogs_pool_index(&pcf_ue_am_pool, pcf_ue_am)); + ogs_assert(pcf_ue_am->association_id); - pcf_ue->supi = ogs_strdup(supi); - ogs_assert(pcf_ue->supi); - ogs_hash_set(self.supi_hash, pcf_ue->supi, strlen(pcf_ue->supi), pcf_ue); + pcf_ue_am->supi = ogs_strdup(supi); + ogs_assert(pcf_ue_am->supi); + ogs_hash_set(self.supi_am_hash, pcf_ue_am->supi, strlen(pcf_ue_am->supi), pcf_ue_am); memset(&e, 0, sizeof(e)); - e.pcf_ue_id = pcf_ue->id; - ogs_fsm_init(&pcf_ue->sm, pcf_am_state_initial, pcf_am_state_final, &e); + e.pcf_ue_am_id = pcf_ue_am->id; + ogs_fsm_init(&pcf_ue_am->sm, pcf_am_state_initial, pcf_am_state_final, &e); - ogs_list_add(&self.pcf_ue_list, pcf_ue); + ogs_list_add(&self.pcf_ue_am_list, pcf_ue_am); - return pcf_ue; + return pcf_ue_am; } -void pcf_ue_remove(pcf_ue_t *pcf_ue) +void pcf_ue_am_remove(pcf_ue_am_t *pcf_ue_am) { pcf_event_t e; - ogs_assert(pcf_ue); + ogs_assert(pcf_ue_am); - ogs_list_remove(&self.pcf_ue_list, pcf_ue); + ogs_list_remove(&self.pcf_ue_am_list, pcf_ue_am); memset(&e, 0, sizeof(e)); - e.pcf_ue_id = pcf_ue->id; - ogs_fsm_fini(&pcf_ue->sm, &e); + e.pcf_ue_am_id = pcf_ue_am->id; + ogs_fsm_fini(&pcf_ue_am->sm, &e); /* Free SBI object memory */ - if (ogs_list_count(&pcf_ue->sbi.xact_list)) + if (ogs_list_count(&pcf_ue_am->sbi.xact_list)) ogs_error("UE transaction [%d]", - ogs_list_count(&pcf_ue->sbi.xact_list)); - ogs_sbi_object_free(&pcf_ue->sbi); + ogs_list_count(&pcf_ue_am->sbi.xact_list)); + ogs_sbi_object_free(&pcf_ue_am->sbi); - pcf_sess_remove_all(pcf_ue); + OpenAPI_policy_association_request_free(pcf_ue_am->policy_association_request); + if (pcf_ue_am->subscribed_ue_ambr) + OpenAPI_ambr_free(pcf_ue_am->subscribed_ue_ambr); - OpenAPI_policy_association_request_free(pcf_ue->policy_association_request); - if (pcf_ue->subscribed_ue_ambr) - OpenAPI_ambr_free(pcf_ue->subscribed_ue_ambr); + ogs_assert(pcf_ue_am->association_id); + ogs_free(pcf_ue_am->association_id); - ogs_assert(pcf_ue->association_id); - ogs_free(pcf_ue->association_id); + ogs_assert(pcf_ue_am->supi); + ogs_hash_set(self.supi_am_hash, pcf_ue_am->supi, strlen(pcf_ue_am->supi), NULL); + ogs_free(pcf_ue_am->supi); - ogs_assert(pcf_ue->supi); - ogs_hash_set(self.supi_hash, pcf_ue->supi, strlen(pcf_ue->supi), NULL); - ogs_free(pcf_ue->supi); + if (pcf_ue_am->notification_uri) + ogs_free(pcf_ue_am->notification_uri); + if (pcf_ue_am->namf.client) + ogs_sbi_client_remove(pcf_ue_am->namf.client); - if (pcf_ue->notification_uri) - ogs_free(pcf_ue->notification_uri); - if (pcf_ue->namf.client) - ogs_sbi_client_remove(pcf_ue->namf.client); + if (pcf_ue_am->gpsi) + ogs_free(pcf_ue_am->gpsi); + if (pcf_ue_am->pei) + ogs_free(pcf_ue_am->pei); - if (pcf_ue->gpsi) - ogs_free(pcf_ue->gpsi); - if (pcf_ue->pei) - ogs_free(pcf_ue->pei); - - ogs_pool_id_free(&pcf_ue_pool, pcf_ue); + ogs_pool_id_free(&pcf_ue_am_pool, pcf_ue_am); } -void pcf_ue_remove_all(void) +void pcf_ue_am_remove_all(void) { - pcf_ue_t *pcf_ue = NULL, *next = NULL;; + pcf_ue_am_t *pcf_ue_am = NULL, *next = NULL;; - ogs_list_for_each_safe(&self.pcf_ue_list, next, pcf_ue) - pcf_ue_remove(pcf_ue); + ogs_list_for_each_safe(&self.pcf_ue_am_list, next, pcf_ue_am) + pcf_ue_am_remove(pcf_ue_am); } -pcf_ue_t *pcf_ue_find_by_supi(char *supi) +pcf_ue_am_t *pcf_ue_am_find_by_supi(char *supi) { ogs_assert(supi); - return (pcf_ue_t *)ogs_hash_get(self.supi_hash, supi, strlen(supi)); + return (pcf_ue_am_t *)ogs_hash_get(self.supi_am_hash, supi, strlen(supi)); } -pcf_ue_t *pcf_ue_find_by_association_id(char *association_id) +pcf_ue_am_t *pcf_ue_am_find_by_association_id(char *association_id) { ogs_assert(association_id); - return ogs_pool_find(&pcf_ue_pool, atoll(association_id)); + return ogs_pool_find(&pcf_ue_am_pool, atoll(association_id)); } -pcf_sess_t *pcf_sess_add(pcf_ue_t *pcf_ue, uint8_t psi) +pcf_ue_sm_t *pcf_ue_sm_add(char *supi) +{ + pcf_ue_sm_t *pcf_ue_sm = NULL; + + ogs_assert(supi); + + ogs_pool_id_calloc(&pcf_ue_sm_pool, &pcf_ue_sm); + ogs_assert(pcf_ue_sm); + + pcf_ue_sm->supi = ogs_strdup(supi); + ogs_assert(pcf_ue_sm->supi); + ogs_hash_set(self.supi_sm_hash, pcf_ue_sm->supi, strlen(pcf_ue_sm->supi), pcf_ue_sm); + + ogs_list_add(&self.pcf_ue_sm_list, pcf_ue_sm); + + return pcf_ue_sm; +} + +void pcf_ue_sm_remove(pcf_ue_sm_t *pcf_ue_sm) +{ + ogs_assert(pcf_ue_sm); + + ogs_list_remove(&self.pcf_ue_sm_list, pcf_ue_sm); + + pcf_sess_remove_all(pcf_ue_sm); + + ogs_assert(pcf_ue_sm->supi); + ogs_hash_set(self.supi_sm_hash, pcf_ue_sm->supi, strlen(pcf_ue_sm->supi), NULL); + ogs_free(pcf_ue_sm->supi); + + if (pcf_ue_sm->gpsi) + ogs_free(pcf_ue_sm->gpsi); + + ogs_pool_id_free(&pcf_ue_sm_pool, pcf_ue_sm); +} + +void pcf_ue_sm_remove_all(void) +{ + pcf_ue_sm_t *pcf_ue_sm = NULL, *next = NULL;; + + ogs_list_for_each_safe(&self.pcf_ue_sm_list, next, pcf_ue_sm) + pcf_ue_sm_remove(pcf_ue_sm); +} + +pcf_ue_sm_t *pcf_ue_sm_find_by_supi(char *supi) +{ + ogs_assert(supi); + return (pcf_ue_sm_t *)ogs_hash_get(self.supi_sm_hash, supi, strlen(supi)); +} + +pcf_ue_sm_t *pcf_ue_sm_find_by_association_id(char *association_id) +{ + ogs_assert(association_id); + return ogs_pool_find(&pcf_ue_sm_pool, atoll(association_id)); +} + +pcf_sess_t *pcf_sess_add(pcf_ue_sm_t *pcf_ue_sm, uint8_t psi) { pcf_event_t e; pcf_sess_t *sess = NULL; - ogs_assert(pcf_ue); + ogs_assert(pcf_ue_sm); ogs_assert(psi != OGS_NAS_PDU_SESSION_IDENTITY_UNASSIGNED); ogs_pool_id_calloc(&pcf_sess_pool, &sess); @@ -465,7 +528,7 @@ pcf_sess_t *pcf_sess_add(pcf_ue_t *pcf_ue, uint8_t psi) (int)ogs_pool_index(&pcf_sess_pool, sess)); ogs_assert(sess->sm_policy_id); - sess->pcf_ue_id = pcf_ue->id; + sess->pcf_ue_sm_id = pcf_ue_sm->id; sess->psi = psi; sess->s_nssai.sst = 0; @@ -475,7 +538,7 @@ pcf_sess_t *pcf_sess_add(pcf_ue_t *pcf_ue, uint8_t psi) e.sess_id = sess->id; ogs_fsm_init(&sess->sm, pcf_sm_state_initial, pcf_sm_state_final, &e); - ogs_list_add(&pcf_ue->sess_list, sess); + ogs_list_add(&pcf_ue_sm->sess_list, sess); return sess; } @@ -483,13 +546,13 @@ pcf_sess_t *pcf_sess_add(pcf_ue_t *pcf_ue, uint8_t psi) void pcf_sess_remove(pcf_sess_t *sess) { pcf_event_t e; - pcf_ue_t *pcf_ue = NULL; + pcf_ue_sm_t *pcf_ue_sm = NULL; ogs_assert(sess); - pcf_ue = pcf_ue_find_by_id(sess->pcf_ue_id); - ogs_assert(pcf_ue); + pcf_ue_sm = pcf_ue_sm_find_by_id(sess->pcf_ue_sm_id); + ogs_assert(pcf_ue_sm); - ogs_list_remove(&pcf_ue->sess_list, sess); + ogs_list_remove(&pcf_ue_sm->sess_list, sess); memset(&e, 0, sizeof(e)); e.sess_id = sess->id; @@ -534,13 +597,13 @@ void pcf_sess_remove(pcf_sess_t *sess) ogs_pool_id_free(&pcf_sess_pool, sess); } -void pcf_sess_remove_all(pcf_ue_t *pcf_ue) +void pcf_sess_remove_all(pcf_ue_sm_t *pcf_ue_sm) { pcf_sess_t *sess = NULL, *next_sess = NULL; - ogs_assert(pcf_ue); + ogs_assert(pcf_ue_sm); - ogs_list_for_each_safe(&pcf_ue->sess_list, next_sess, sess) + ogs_list_for_each_safe(&pcf_ue_sm->sess_list, next_sess, sess) pcf_sess_remove(sess); } @@ -634,11 +697,13 @@ pcf_sess_t *pcf_sess_find_by_sm_policy_id(char *sm_policy_id) return pcf_sess_find(atoll(sm_policy_id)); } -pcf_sess_t *pcf_sess_find_by_psi(pcf_ue_t *pcf_ue, uint8_t psi) +pcf_sess_t *pcf_sess_find_by_psi(pcf_ue_sm_t *pcf_ue_sm, uint8_t psi) { pcf_sess_t *sess = NULL; - ogs_list_for_each(&pcf_ue->sess_list, sess) + ogs_assert(pcf_ue_sm); + + ogs_list_for_each(&pcf_ue_sm->sess_list, sess) if (psi == sess->psi) return sess; return NULL; @@ -661,7 +726,7 @@ pcf_sess_t *pcf_sess_find_by_ipv4addr(char *ipv4addr_string) } int pcf_sessions_number_by_snssai_and_dnn( - pcf_ue_t *pcf_ue, ogs_s_nssai_t *s_nssai, char *dnn) + pcf_ue_sm_t *pcf_ue_sm, ogs_s_nssai_t *s_nssai, char *dnn) { int number_of_sessions = 0; pcf_sess_t *sess = NULL; @@ -669,7 +734,7 @@ int pcf_sessions_number_by_snssai_and_dnn( ogs_assert(s_nssai); ogs_assert(dnn); - ogs_list_for_each(&pcf_ue->sess_list, sess) + ogs_list_for_each(&pcf_ue_sm->sess_list, sess) if (sess->s_nssai.sst == s_nssai->sst && sess->dnn && ogs_strcasecmp(sess->dnn, dnn) == 0) number_of_sessions++; @@ -721,9 +786,14 @@ pcf_sess_t *pcf_sess_find_by_ipv6prefix(char *ipv6prefix_string) &ipv6prefix, (ipv6prefix.len >> 3) + 1); } -pcf_ue_t *pcf_ue_find_by_id(ogs_pool_id_t id) +pcf_ue_am_t *pcf_ue_am_find_by_id(ogs_pool_id_t id) { - return ogs_pool_find_by_id(&pcf_ue_pool, id); + return ogs_pool_find_by_id(&pcf_ue_am_pool, id); +} + +pcf_ue_sm_t *pcf_ue_sm_find_by_id(ogs_pool_id_t id) +{ + return ogs_pool_find_by_id(&pcf_ue_sm_pool, id); } pcf_sess_t *pcf_sess_find_by_id(ogs_pool_id_t id) @@ -800,9 +870,9 @@ pcf_app_t *pcf_app_find_by_app_session_id(char *app_session_id) int pcf_instance_get_load(void) { - return (((ogs_pool_size(&pcf_ue_pool) - - ogs_pool_avail(&pcf_ue_pool)) * 100) / - ogs_pool_size(&pcf_ue_pool)); + return (((ogs_pool_size(&pcf_ue_sm_pool) - + ogs_pool_avail(&pcf_ue_sm_pool)) * 100) / + ogs_pool_size(&pcf_ue_sm_pool)); } int pcf_db_qos_data(char *supi, diff --git a/src/pcf/context.h b/src/pcf/context.h index 7eda1ed8f..029dc76f5 100644 --- a/src/pcf/context.h +++ b/src/pcf/context.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019-2022 by Sukchan Lee + * Copyright (C) 2019-2025 by Sukchan Lee * * This file is part of Open5GS. * @@ -38,14 +38,18 @@ extern int __pcf_log_domain; #define OGS_LOG_DOMAIN __pcf_log_domain typedef struct pcf_context_s { - ogs_list_t pcf_ue_list; - ogs_hash_t *supi_hash; + ogs_list_t pcf_ue_am_list; +#define PCF_UE_SM_IS_LAST_SESSION(__pCF) \ + ((__pCF) && (ogs_list_count(&(__pCF)->sess_list)) == 1) + ogs_list_t pcf_ue_sm_list; + ogs_hash_t *supi_am_hash; + ogs_hash_t *supi_sm_hash; ogs_hash_t *ipv4addr_hash; ogs_hash_t *ipv6prefix_hash; } pcf_context_t; -struct pcf_ue_s { +struct pcf_ue_am_s { ogs_sbi_object_t sbi; ogs_pool_id_t id; ogs_fsm_t sm; @@ -70,10 +74,29 @@ struct pcf_ue_s { OpenAPI_policy_association_request_t *policy_association_request; OpenAPI_ambr_t *subscribed_ue_ambr; +}; + +struct pcf_ue_sm_s { + ogs_lnode_t lnode; + ogs_pool_id_t id; + + char *supi; + char *gpsi; ogs_list_t sess_list; }; +#define PCF_SESS_CLEAR(__sESS) \ + do { \ + pcf_ue_sm_t *pcf_ue_sm = NULL; \ + ogs_assert(__sESS); \ + pcf_ue_sm = pcf_ue_sm_find_by_id((__sESS)->pcf_ue_sm_id); \ + ogs_assert(pcf_ue_sm); \ + if (PCF_UE_SM_IS_LAST_SESSION(pcf_ue_sm)) \ + pcf_ue_sm_remove(pcf_ue_sm); \ + else \ + pcf_sess_remove(__sESS); \ + } while(0) struct pcf_sess_s { ogs_sbi_object_t sbi; ogs_pool_id_t id; @@ -156,7 +179,7 @@ struct pcf_sess_s { ogs_list_t app_list; /* Related Context */ - ogs_pool_id_t pcf_ue_id; + ogs_pool_id_t pcf_ue_sm_id; }; typedef struct pcf_app_s { @@ -181,30 +204,37 @@ pcf_context_t *pcf_self(void); int pcf_context_parse_config(void); -pcf_ue_t *pcf_ue_add(char *supi); -void pcf_ue_remove(pcf_ue_t *pcf_ue); -void pcf_ue_remove_all(void); -pcf_ue_t *pcf_ue_find_by_supi(char *supi); -pcf_ue_t *pcf_ue_find_by_association_id(char *association_id); +pcf_ue_am_t *pcf_ue_am_add(char *supi); +void pcf_ue_am_remove(pcf_ue_am_t *pcf_ue_am); +void pcf_ue_am_remove_all(void); +pcf_ue_am_t *pcf_ue_am_find_by_supi(char *supi); +pcf_ue_am_t *pcf_ue_am_find_by_association_id(char *association_id); -pcf_sess_t *pcf_sess_add(pcf_ue_t *pcf_ue, uint8_t psi); +pcf_ue_sm_t *pcf_ue_sm_add(char *supi); +void pcf_ue_sm_remove(pcf_ue_sm_t *pcf_ue_sm); +void pcf_ue_sm_remove_all(void); +pcf_ue_sm_t *pcf_ue_sm_find_by_supi(char *supi); +pcf_ue_sm_t *pcf_ue_sm_find_by_association_id(char *association_id); + +pcf_sess_t *pcf_sess_add(pcf_ue_sm_t *pcf_ue_sm, uint8_t psi); void pcf_sess_remove(pcf_sess_t *sess); -void pcf_sess_remove_all(pcf_ue_t *pcf_ue); +void pcf_sess_remove_all(pcf_ue_sm_t *pcf_ue_sm); bool pcf_sess_set_ipv4addr(pcf_sess_t *sess, char *ipv4addr); bool pcf_sess_set_ipv6prefix(pcf_sess_t *sess, char *ipv6prefix); pcf_sess_t *pcf_sess_find(uint32_t index); pcf_sess_t *pcf_sess_find_by_sm_policy_id(char *sm_policy_id); -pcf_sess_t *pcf_sess_find_by_psi(pcf_ue_t *pcf_ue, uint8_t psi); -pcf_sess_t *pcf_sess_find_by_dnn(pcf_ue_t *pcf_ue, char *dnn); +pcf_sess_t *pcf_sess_find_by_psi(pcf_ue_sm_t *pcf_ue_sm, uint8_t psi); +pcf_sess_t *pcf_sess_find_by_dnn(pcf_ue_sm_t *pcf_ue_sm, char *dnn); pcf_sess_t *pcf_sess_find_by_ipv4addr(char *ipv4addr_string); pcf_sess_t *pcf_sess_find_by_ipv6addr(char *ipv6addr_string); pcf_sess_t *pcf_sess_find_by_ipv6prefix(char *ipv6prefix_string); int pcf_sessions_number_by_snssai_and_dnn( - pcf_ue_t *pcf_ue, ogs_s_nssai_t *s_nssai, char *dnn); + pcf_ue_sm_t *pcf_ue_sm, ogs_s_nssai_t *s_nssai, char *dnn); -pcf_ue_t *pcf_ue_find_by_id(ogs_pool_id_t id); +pcf_ue_am_t *pcf_ue_am_find_by_id(ogs_pool_id_t id); +pcf_ue_sm_t *pcf_ue_sm_find_by_id(ogs_pool_id_t id); pcf_sess_t *pcf_sess_find_by_id(ogs_pool_id_t id); pcf_app_t *pcf_app_add(pcf_sess_t *sess); diff --git a/src/pcf/event.h b/src/pcf/event.h index 9ecadf287..5fb2117d9 100644 --- a/src/pcf/event.h +++ b/src/pcf/event.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019-2022 by Sukchan Lee + * Copyright (C) 2019-2025 by Sukchan Lee * * This file is part of Open5GS. * @@ -26,14 +26,16 @@ extern "C" { #endif -typedef struct pcf_ue_s pcf_ue_t; +typedef struct pcf_ue_am_s pcf_ue_am_t; +typedef struct pcf_ue_sm_s pcf_ue_sm_t; typedef struct pcf_sess_s pcf_sess_t; typedef struct pcf_app_s pcf_app_t; typedef struct pcf_event_s { ogs_event_t h; - ogs_pool_id_t pcf_ue_id; + ogs_pool_id_t pcf_ue_am_id; + ogs_pool_id_t pcf_ue_sm_id; ogs_pool_id_t sess_id; pcf_app_t *app; } pcf_event_t; diff --git a/src/pcf/namf-build.c b/src/pcf/namf-build.c index 4e99fab39..e1851dc16 100644 --- a/src/pcf/namf-build.c +++ b/src/pcf/namf-build.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 by Sukchan Lee + * Copyright (C) 2019-2025 by Sukchan Lee * * This file is part of Open5GS. * @@ -20,21 +20,21 @@ #include "namf-build.h" ogs_sbi_request_t *pcf_namf_callback_build_am_policy_control( - pcf_ue_t *pcf_ue, void *data) + pcf_ue_am_t *pcf_ue_am, void *data) { ogs_sbi_message_t message; ogs_sbi_request_t *request = NULL; OpenAPI_policy_update_t PolicyUpdate; - ogs_assert(pcf_ue); - ogs_assert(pcf_ue->notification_uri); + ogs_assert(pcf_ue_am); + ogs_assert(pcf_ue_am->notification_uri); memset(&PolicyUpdate, 0, sizeof(PolicyUpdate)); memset(&message, 0, sizeof(message)); message.h.method = (char *)OGS_SBI_HTTP_METHOD_POST; - message.h.uri = pcf_ue->notification_uri; + message.h.uri = pcf_ue_am->notification_uri; message.PolicyUpdate = &PolicyUpdate; diff --git a/src/pcf/namf-build.h b/src/pcf/namf-build.h index acf7058ba..a6958c32b 100644 --- a/src/pcf/namf-build.h +++ b/src/pcf/namf-build.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 by Sukchan Lee + * Copyright (C) 2019-2025 by Sukchan Lee * * This file is part of Open5GS. * @@ -27,7 +27,7 @@ extern "C" { #endif ogs_sbi_request_t *pcf_namf_callback_build_am_policy_control( - pcf_ue_t *pcf_ue, void *data); + pcf_ue_am_t *pcf_ue_am, void *data); #ifdef __cplusplus } diff --git a/src/pcf/nbsf-build.c b/src/pcf/nbsf-build.c index 0454b8df2..f190f86e7 100644 --- a/src/pcf/nbsf-build.c +++ b/src/pcf/nbsf-build.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019-2023 by Sukchan Lee + * Copyright (C) 2019-2025 by Sukchan Lee * * This file is part of Open5GS. * @@ -22,7 +22,7 @@ ogs_sbi_request_t *pcf_nbsf_management_build_register( pcf_sess_t *sess, void *data) { - pcf_ue_t *pcf_ue = NULL; + pcf_ue_sm_t *pcf_ue_sm = NULL; ogs_sbi_message_t message; ogs_sbi_request_t *request = NULL; @@ -40,8 +40,8 @@ ogs_sbi_request_t *pcf_nbsf_management_build_register( int i; ogs_assert(sess); - pcf_ue = pcf_ue_find_by_id(sess->pcf_ue_id); - ogs_assert(pcf_ue); + pcf_ue_sm = pcf_ue_sm_find_by_id(sess->pcf_ue_sm_id); + ogs_assert(pcf_ue_sm); memset(&message, 0, sizeof(message)); message.h.method = (char *)OGS_SBI_HTTP_METHOD_POST; @@ -53,8 +53,8 @@ ogs_sbi_request_t *pcf_nbsf_management_build_register( memset(&PcfBinding, 0, sizeof(PcfBinding)); memset(&sNssai, 0, sizeof(sNssai)); - PcfBinding.supi = pcf_ue->supi; - PcfBinding.gpsi = pcf_ue->gpsi; + PcfBinding.supi = pcf_ue_sm->supi; + PcfBinding.gpsi = pcf_ue_sm->gpsi; PcfBinding.ipv4_addr = sess->ipv4addr_string; PcfBinding.ipv6_prefix = sess->ipv6prefix_string; @@ -183,14 +183,14 @@ end: ogs_sbi_request_t *pcf_nbsf_management_build_de_register( pcf_sess_t *sess, void *data) { - pcf_ue_t *pcf_ue = NULL; + pcf_ue_sm_t *pcf_ue_sm = NULL; ogs_sbi_message_t message; ogs_sbi_request_t *request = NULL; ogs_assert(sess); - pcf_ue = pcf_ue_find_by_id(sess->pcf_ue_id); - ogs_assert(pcf_ue); + pcf_ue_sm = pcf_ue_sm_find_by_id(sess->pcf_ue_sm_id); + ogs_assert(pcf_ue_sm); ogs_assert(sess->binding.resource_uri); memset(&message, 0, sizeof(message)); diff --git a/src/pcf/nbsf-handler.c b/src/pcf/nbsf-handler.c index 2f4c39794..1dc63a04d 100644 --- a/src/pcf/nbsf-handler.c +++ b/src/pcf/nbsf-handler.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019,2020 by Sukchan Lee + * Copyright (C) 2019-2025 by Sukchan Lee * * This file is part of Open5GS. * @@ -26,7 +26,7 @@ bool pcf_nbsf_management_handle_register( { int rv, status = 0; char *strerror = NULL; - pcf_ue_t *pcf_ue = NULL; + pcf_ue_sm_t *pcf_ue_sm = NULL; ogs_sbi_server_t *server = NULL; ogs_sbi_header_t header; @@ -42,27 +42,27 @@ bool pcf_nbsf_management_handle_register( ogs_sockaddr_t *addr = NULL, *addr6 = NULL; ogs_assert(sess); - pcf_ue = pcf_ue_find_by_id(sess->pcf_ue_id); - ogs_assert(pcf_ue); + pcf_ue_sm = pcf_ue_sm_find_by_id(sess->pcf_ue_sm_id); + ogs_assert(pcf_ue_sm); ogs_assert(stream); server = ogs_sbi_server_from_stream(stream); ogs_assert(server); ogs_assert(recvmsg); - ogs_assert(pcf_ue->supi); + ogs_assert(pcf_ue_sm->supi); ogs_assert(sess->dnn); if (!recvmsg->http.location) { strerror = ogs_msprintf("[%s:%d] No http.location", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } if (!recvmsg->PcfBinding) { strerror = ogs_msprintf("[%s:%d] No PcfBinding", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } @@ -80,13 +80,13 @@ bool pcf_nbsf_management_handle_register( rv = ogs_sbi_parse_header(&message, &header); if (rv != OGS_OK) { strerror = ogs_msprintf("[%s:%d] Cannot parse http.location [%s]", - pcf_ue->supi, sess->psi, recvmsg->http.location); + pcf_ue_sm->supi, sess->psi, recvmsg->http.location); goto cleanup; } if (!message.h.resource.component[1]) { strerror = ogs_msprintf("[%s:%d] No Binding ID [%s]", - pcf_ue->supi, sess->psi, recvmsg->http.location); + pcf_ue_sm->supi, sess->psi, recvmsg->http.location); ogs_sbi_header_free(&header); goto cleanup; @@ -96,18 +96,18 @@ bool pcf_nbsf_management_handle_register( &scheme, &fqdn, &fqdn_port, &addr, &addr6, header.uri); if (rc == false || scheme == OpenAPI_uri_scheme_NULL) { strerror = ogs_msprintf("[%s:%d] Invalid URI [%s]", - pcf_ue->supi, sess->psi, header.uri); + pcf_ue_sm->supi, sess->psi, header.uri); ogs_sbi_header_free(&header); goto cleanup; } client = ogs_sbi_client_find(scheme, fqdn, fqdn_port, addr, addr6); if (!client) { - ogs_debug("[%s:%d] ogs_sbi_client_add()", pcf_ue->supi, sess->psi); + ogs_debug("[%s:%d] ogs_sbi_client_add()", pcf_ue_sm->supi, sess->psi); client = ogs_sbi_client_add(scheme, fqdn, fqdn_port, addr, addr6); if (!client) { strerror = ogs_msprintf("[%s:%d] ogs_sbi_client_add() failed", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); ogs_sbi_header_free(&header); ogs_free(fqdn); diff --git a/src/pcf/nnrf-handler.c b/src/pcf/nnrf-handler.c index 4a3247580..634296cf7 100644 --- a/src/pcf/nnrf-handler.c +++ b/src/pcf/nnrf-handler.c @@ -29,7 +29,8 @@ void pcf_nnrf_handle_nf_discover( ogs_sbi_service_type_e service_type = OGS_SBI_SERVICE_TYPE_NULL; ogs_sbi_discovery_option_t *discovery_option = NULL; - pcf_ue_t *pcf_ue = NULL; + pcf_ue_sm_t *pcf_ue_sm = NULL; + pcf_ue_am_t *pcf_ue_am = NULL; pcf_sess_t *sess = NULL; OpenAPI_nf_type_e target_nf_type = OpenAPI_nf_type_NULL; @@ -60,13 +61,13 @@ void pcf_nnrf_handle_nf_discover( } if (sbi_object->type == OGS_SBI_OBJ_UE_TYPE) { - pcf_ue = pcf_ue_find_by_id(sbi_object_id); - ogs_assert(pcf_ue); + pcf_ue_am = pcf_ue_am_find_by_id(sbi_object_id); + ogs_assert(pcf_ue_am); } else if (sbi_object->type == OGS_SBI_OBJ_SESS_TYPE) { sess = pcf_sess_find_by_id(sbi_object_id); ogs_assert(sess); - pcf_ue = pcf_ue_find_by_id(sess->pcf_ue_id); - ogs_assert(pcf_ue); + pcf_ue_sm = pcf_ue_sm_find_by_id(sess->pcf_ue_sm_id); + ogs_assert(pcf_ue_sm); } else { ogs_fatal("(NF discover) Not implemented [%s:%d]", ogs_sbi_service_type_to_name(service_type), sbi_object->type); @@ -78,8 +79,9 @@ void pcf_nnrf_handle_nf_discover( nf_instance = ogs_sbi_nf_instance_find_by_discovery_param( target_nf_type, requester_nf_type, discovery_option); if (!nf_instance) { - ogs_error("[%s:%d] (NF discover) No [%s:%s]", - pcf_ue ? pcf_ue->supi : "Unknown", + ogs_error("[%s:%s:%d] (NF discover) No [%s:%s]", + pcf_ue_am ? pcf_ue_am->supi : "Unknown", + pcf_ue_sm ? pcf_ue_sm->supi : "Unknown", sess ? sess->psi : 0, ogs_sbi_service_type_to_name(service_type), OpenAPI_nf_type_ToString(requester_nf_type)); diff --git a/src/pcf/npcf-handler.c b/src/pcf/npcf-handler.c index 930567ffc..f4098836e 100644 --- a/src/pcf/npcf-handler.c +++ b/src/pcf/npcf-handler.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019-2023 by Sukchan Lee + * Copyright (C) 2019-2025 by Sukchan Lee * * This file is part of Open5GS. * @@ -21,7 +21,7 @@ #include "npcf-handler.h" -bool pcf_npcf_am_policy_control_handle_create(pcf_ue_t *pcf_ue, +bool pcf_npcf_am_policy_control_handle_create(pcf_ue_am_t *pcf_ue_am, ogs_sbi_stream_t *stream, ogs_sbi_message_t *message) { bool rc; @@ -40,7 +40,7 @@ bool pcf_npcf_am_policy_control_handle_create(pcf_ue_t *pcf_ue, uint16_t fqdn_port = 0; ogs_sockaddr_t *addr = NULL, *addr6 = NULL; - ogs_assert(pcf_ue); + ogs_assert(pcf_ue_am); ogs_assert(stream); server = ogs_sbi_server_from_stream(stream); ogs_assert(server); @@ -48,35 +48,35 @@ bool pcf_npcf_am_policy_control_handle_create(pcf_ue_t *pcf_ue, PolicyAssociationRequest = message->PolicyAssociationRequest; if (!PolicyAssociationRequest) { - ogs_error("[%s] No PolicyAssociationRequest", pcf_ue->supi); + ogs_error("[%s] No PolicyAssociationRequest", pcf_ue_am->supi); ogs_assert(true == ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, - message, "[%s] No PolicyAssociationRequest", pcf_ue->supi, + message, "[%s] No PolicyAssociationRequest", pcf_ue_am->supi, NULL)); return false; } if (!PolicyAssociationRequest->notification_uri) { - ogs_error("[%s] No notificationUri", pcf_ue->supi); + ogs_error("[%s] No notificationUri", pcf_ue_am->supi); ogs_assert(true == ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, - message, "No notificationUri", pcf_ue->supi, NULL)); + message, "No notificationUri", pcf_ue_am->supi, NULL)); return false; } if (!PolicyAssociationRequest->supi) { - ogs_error("[%s] No supi", pcf_ue->supi); + ogs_error("[%s] No supi", pcf_ue_am->supi); ogs_assert(true == ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, - message, "No supi", pcf_ue->supi, NULL)); + message, "No supi", pcf_ue_am->supi, NULL)); return false; } if (!PolicyAssociationRequest->supp_feat) { - ogs_error("[%s] No suppFeat", pcf_ue->supi); + ogs_error("[%s] No suppFeat", pcf_ue_am->supi); ogs_assert(true == ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, - message, "No suppFeat", pcf_ue->supi, NULL)); + message, "No suppFeat", pcf_ue_am->supi, NULL)); return false; } @@ -84,18 +84,18 @@ bool pcf_npcf_am_policy_control_handle_create(pcf_ue_t *pcf_ue, PolicyAssociationRequest->notification_uri); if (rc == false || scheme == OpenAPI_uri_scheme_NULL) { ogs_error("[%s] Invalid URI [%s]", - pcf_ue->supi, PolicyAssociationRequest->notification_uri); + pcf_ue_am->supi, PolicyAssociationRequest->notification_uri); ogs_assert(true == ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, - message, "[%s] Invalid URI", pcf_ue->supi, NULL)); + message, "[%s] Invalid URI", pcf_ue_am->supi, NULL)); return false; } - if (pcf_ue->notification_uri) - ogs_free(pcf_ue->notification_uri); - pcf_ue->notification_uri = ogs_strdup( + if (pcf_ue_am->notification_uri) + ogs_free(pcf_ue_am->notification_uri); + pcf_ue_am->notification_uri = ogs_strdup( PolicyAssociationRequest->notification_uri); - ogs_assert(pcf_ue->notification_uri); + ogs_assert(pcf_ue_am->notification_uri); client = ogs_sbi_client_find(scheme, fqdn, fqdn_port, addr, addr6); if (!client) { @@ -111,7 +111,7 @@ bool pcf_npcf_am_policy_control_handle_create(pcf_ue_t *pcf_ue, return false; } } - OGS_SBI_SETUP_CLIENT(&pcf_ue->namf, client); + OGS_SBI_SETUP_CLIENT(&pcf_ue_am->namf, client); ogs_free(fqdn); ogs_freeaddrinfo(addr); @@ -120,26 +120,26 @@ bool pcf_npcf_am_policy_control_handle_create(pcf_ue_t *pcf_ue, supported_features = ogs_uint64_from_string_hexadecimal( PolicyAssociationRequest->supp_feat); - pcf_ue->am_policy_control_features &= supported_features; + pcf_ue_am->am_policy_control_features &= supported_features; if (PolicyAssociationRequest->gpsi) { - if (pcf_ue->gpsi) - ogs_free(pcf_ue->gpsi); - pcf_ue->gpsi = ogs_strdup(PolicyAssociationRequest->gpsi); + if (pcf_ue_am->gpsi) + ogs_free(pcf_ue_am->gpsi); + pcf_ue_am->gpsi = ogs_strdup(PolicyAssociationRequest->gpsi); } - pcf_ue->access_type = PolicyAssociationRequest->access_type; + pcf_ue_am->access_type = PolicyAssociationRequest->access_type; if (PolicyAssociationRequest->pei) { - if (pcf_ue->pei) - ogs_free(pcf_ue->pei); - pcf_ue->pei = ogs_strdup(PolicyAssociationRequest->pei); + if (pcf_ue_am->pei) + ogs_free(pcf_ue_am->pei); + pcf_ue_am->pei = ogs_strdup(PolicyAssociationRequest->pei); } Guami = PolicyAssociationRequest->guami; if (Guami && Guami->amf_id && Guami->plmn_id && Guami->plmn_id->mnc && Guami->plmn_id->mcc) { - ogs_sbi_parse_guami(&pcf_ue->guami, PolicyAssociationRequest->guami); + ogs_sbi_parse_guami(&pcf_ue_am->guami, PolicyAssociationRequest->guami); } OpenAPI_list_for_each(PolicyAssociationRequest->allowed_snssais, node) { @@ -149,26 +149,27 @@ bool pcf_npcf_am_policy_control_handle_create(pcf_ue_t *pcf_ue, s_nssai.sst = Snssai->sst; s_nssai.sd = ogs_s_nssai_sd_from_string(Snssai->sd); - pcf_metrics_inst_by_slice_add(&pcf_ue->guami.plmn_id, + pcf_metrics_inst_by_slice_add(&pcf_ue_am->guami.plmn_id, &s_nssai, PCF_METR_CTR_PA_POLICYAMASSOREQ, 1); } else { - ogs_error("[%s] No Snssai", pcf_ue->supi); + ogs_error("[%s] No Snssai", pcf_ue_am->supi); } } if (PolicyAssociationRequest->rat_type) - pcf_ue->rat_type = PolicyAssociationRequest->rat_type; + pcf_ue_am->rat_type = PolicyAssociationRequest->rat_type; - pcf_ue->policy_association_request = + pcf_ue_am->policy_association_request = OpenAPI_policy_association_request_copy( - pcf_ue->policy_association_request, + pcf_ue_am->policy_association_request, message->PolicyAssociationRequest); if (PolicyAssociationRequest->ue_ambr) - pcf_ue->subscribed_ue_ambr = OpenAPI_ambr_copy( - pcf_ue->subscribed_ue_ambr, PolicyAssociationRequest->ue_ambr); + pcf_ue_am->subscribed_ue_ambr = OpenAPI_ambr_copy( + pcf_ue_am->subscribed_ue_ambr, + PolicyAssociationRequest->ue_ambr); - if (ogs_sbi_supi_in_vplmn(pcf_ue->supi) == true) { + if (ogs_sbi_supi_in_vplmn(pcf_ue_am->supi) == true) { /* Visited PLMN */ OpenAPI_policy_association_t PolicyAssociation; @@ -177,9 +178,9 @@ bool pcf_npcf_am_policy_control_handle_create(pcf_ue_t *pcf_ue, ogs_sbi_response_t *response = NULL; memset(&PolicyAssociation, 0, sizeof(PolicyAssociation)); - PolicyAssociation.request = pcf_ue->policy_association_request; + PolicyAssociation.request = pcf_ue_am->policy_association_request; PolicyAssociation.supp_feat = - ogs_uint64_to_string(pcf_ue->am_policy_control_features); + ogs_uint64_to_string(pcf_ue_am->am_policy_control_features); ogs_assert(PolicyAssociation.supp_feat); memset(&header, 0, sizeof(header)); @@ -187,7 +188,7 @@ bool pcf_npcf_am_policy_control_handle_create(pcf_ue_t *pcf_ue, (char *)OGS_SBI_SERVICE_NAME_NPCF_AM_POLICY_CONTROL; header.api.version = (char *)OGS_SBI_API_V1; header.resource.component[0] = (char *)OGS_SBI_RESOURCE_NAME_POLICIES; - header.resource.component[1] = pcf_ue->association_id; + header.resource.component[1] = pcf_ue_am->association_id; memset(&sendmsg, 0, sizeof(sendmsg)); sendmsg.PolicyAssociation = &PolicyAssociation; @@ -205,8 +206,8 @@ bool pcf_npcf_am_policy_control_handle_create(pcf_ue_t *pcf_ue, return true; } else { /* Home PLMN */ - r = pcf_ue_sbi_discover_and_send(OGS_SBI_SERVICE_TYPE_NUDR_DR, NULL, - pcf_nudr_dr_build_query_am_data, pcf_ue, stream, NULL); + r = pcf_ue_am_sbi_discover_and_send(OGS_SBI_SERVICE_TYPE_NUDR_DR, NULL, + pcf_nudr_dr_build_query_am_data, pcf_ue_am, stream, NULL); ogs_expect(r == OGS_OK); ogs_assert(r != OGS_ERROR); @@ -221,7 +222,7 @@ bool pcf_npcf_smpolicycontrol_handle_create(pcf_sess_t *sess, int status = 0; int r; char *strerror = NULL; - pcf_ue_t *pcf_ue = NULL; + pcf_ue_sm_t *pcf_ue_sm = NULL; OpenAPI_sm_policy_context_data_t *SmPolicyContextData = NULL; OpenAPI_plmn_id_nid_t *servingNetwork = NULL; @@ -236,47 +237,47 @@ bool pcf_npcf_smpolicycontrol_handle_create(pcf_sess_t *sess, char *home_network_domain = NULL; ogs_assert(sess); - pcf_ue = pcf_ue_find_by_id(sess->pcf_ue_id); + pcf_ue_sm = pcf_ue_sm_find_by_id(sess->pcf_ue_sm_id); ogs_assert(stream); ogs_assert(message); SmPolicyContextData = message->SmPolicyContextData; if (!SmPolicyContextData) { strerror = ogs_msprintf("[%s:%d] No SmPolicyContextData", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } if (!SmPolicyContextData->supi) { - strerror = ogs_msprintf("[%s:%d] No supi", pcf_ue->supi, sess->psi); + strerror = ogs_msprintf("[%s:%d] No supi", pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } if (!SmPolicyContextData->pdu_session_id) { strerror = ogs_msprintf("[%s:%d] No pduSessionId", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } if (!SmPolicyContextData->pdu_session_type) { strerror = ogs_msprintf("[%s:%d] No pduSessionType", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } if (!SmPolicyContextData->dnn) { - strerror = ogs_msprintf("[%s:%d] No dnn", pcf_ue->supi, sess->psi); + strerror = ogs_msprintf("[%s:%d] No dnn", pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } if (!SmPolicyContextData->notification_uri) { strerror = ogs_msprintf("[%s:%d] No notificationUri", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } @@ -285,7 +286,7 @@ bool pcf_npcf_smpolicycontrol_handle_create(pcf_sess_t *sess, !SmPolicyContextData->ipv6_address_prefix) { strerror = ogs_msprintf( "[%s:%d] No IPv4 address[%p] or IPv6 prefix[%p]", - pcf_ue->supi, sess->psi, + pcf_ue_sm->supi, sess->psi, SmPolicyContextData->ipv4_address, SmPolicyContextData->ipv6_address_prefix); status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; @@ -295,7 +296,7 @@ bool pcf_npcf_smpolicycontrol_handle_create(pcf_sess_t *sess, sliceInfo = SmPolicyContextData->slice_info; if (!sliceInfo) { strerror = ogs_msprintf("[%s:%d] No sliceInfo", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } @@ -304,13 +305,13 @@ bool pcf_npcf_smpolicycontrol_handle_create(pcf_sess_t *sess, if (servingNetwork) { if (!servingNetwork->mcc) { strerror = ogs_msprintf("[%s:%d] No servingNetwork->mcc", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } if (!servingNetwork->mnc) { strerror = ogs_msprintf("[%s:%d] No servingNetwork->mnc", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } @@ -322,11 +323,18 @@ bool pcf_npcf_smpolicycontrol_handle_create(pcf_sess_t *sess, SmPolicyContextData->notification_uri); if (rc == false || scheme == OpenAPI_uri_scheme_NULL) { strerror = ogs_msprintf("[%s:%d] Invalid URI [%s]", - pcf_ue->supi, sess->psi, SmPolicyContextData->notification_uri); + pcf_ue_sm->supi, sess->psi, + SmPolicyContextData->notification_uri); status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } + if (SmPolicyContextData->gpsi) { + if (pcf_ue_sm->gpsi) + ogs_free(pcf_ue_sm->gpsi); + pcf_ue_sm->gpsi = ogs_strdup(SmPolicyContextData->gpsi); + } + if (SmPolicyContextData->supp_feat) { uint64_t supported_features = ogs_uint64_from_string_hexadecimal( @@ -393,16 +401,16 @@ bool pcf_npcf_smpolicycontrol_handle_create(pcf_sess_t *sess, * by comparing the MNC part of the SUPI and full-DNN. */ if (mcc && mnc && - strncmp(pcf_ue->supi, "imsi-", strlen("imsi-")) == 0) { + strncmp(pcf_ue_sm->supi, "imsi-", strlen("imsi-")) == 0) { int mnc_len = 0; char buf[OGS_PLMNIDSTRLEN]; ogs_snprintf(buf, OGS_PLMNIDSTRLEN, "%03d%02d", mcc, mnc); - if (strncmp(pcf_ue->supi + 5, buf, strlen(buf)) == 0) + if (strncmp(pcf_ue_sm->supi + 5, buf, strlen(buf)) == 0) mnc_len = 2; ogs_snprintf(buf, OGS_PLMNIDSTRLEN, "%03d%03d", mcc, mnc); - if (strncmp(pcf_ue->supi + 5, buf, strlen(buf)) == 0) + if (strncmp(pcf_ue_sm->supi + 5, buf, strlen(buf)) == 0) mnc_len = 3; /* Change Home PLMN for VPLMN */ @@ -458,10 +466,12 @@ bool pcf_npcf_smpolicycontrol_handle_create(pcf_sess_t *sess, OpenAPI_clear_and_free_string_list(sess->ipv4_frame_route_list); sess->ipv4_frame_route_list = OpenAPI_list_create(); - OpenAPI_list_for_each(SmPolicyContextData->ipv4_frame_route_list, node) { + OpenAPI_list_for_each( + SmPolicyContextData->ipv4_frame_route_list, node) { if (!node->data) continue; - OpenAPI_list_add(sess->ipv4_frame_route_list, ogs_strdup(node->data)); + OpenAPI_list_add( + sess->ipv4_frame_route_list, ogs_strdup(node->data)); } } @@ -470,19 +480,23 @@ bool pcf_npcf_smpolicycontrol_handle_create(pcf_sess_t *sess, OpenAPI_clear_and_free_string_list(sess->ipv6_frame_route_list); sess->ipv6_frame_route_list = OpenAPI_list_create(); - OpenAPI_list_for_each(SmPolicyContextData->ipv6_frame_route_list, node) { + OpenAPI_list_for_each( + SmPolicyContextData->ipv6_frame_route_list, node) { if (!node->data) continue; - OpenAPI_list_add(sess->ipv6_frame_route_list, ogs_strdup(node->data)); + OpenAPI_list_add( + sess->ipv6_frame_route_list, ogs_strdup(node->data)); } } sess->s_nssai.sst = sliceInfo->sst; sess->s_nssai.sd = ogs_s_nssai_sd_from_string(sliceInfo->sd); - pcf_metrics_inst_by_slice_add(&pcf_ue->guami.plmn_id, + pcf_metrics_inst_by_slice_add( + sess->home.presence == true ? &sess->home.plmn_id : NULL, &sess->s_nssai, PCF_METR_GAUGE_PA_SESSIONNBR, 1); - pcf_metrics_inst_by_slice_add(&pcf_ue->guami.plmn_id, + pcf_metrics_inst_by_slice_add( + sess->home.presence == true ? &sess->home.plmn_id : NULL, &sess->s_nssai, PCF_METR_CTR_PA_POLICYSMASSOREQ, 1); if (SmPolicyContextData->subs_sess_ambr) @@ -493,7 +507,7 @@ bool pcf_npcf_smpolicycontrol_handle_create(pcf_sess_t *sess, sess->subscribed_default_qos = OpenAPI_subscribed_default_qos_copy( sess->subscribed_default_qos, SmPolicyContextData->subs_def_qos); - if (ogs_sbi_supi_in_vplmn(pcf_ue->supi) == true) { + if (ogs_sbi_supi_in_vplmn(pcf_ue_sm->supi) == true) { /* Visited PLMN */ r = pcf_sess_sbi_discover_and_send( OGS_SBI_SERVICE_TYPE_NBSF_MANAGEMENT, NULL, @@ -544,20 +558,20 @@ bool pcf_npcf_smpolicycontrol_handle_delete(pcf_sess_t *sess, int r; int status = 0; char *strerror = NULL; - pcf_ue_t *pcf_ue = NULL; + pcf_ue_sm_t *pcf_ue_sm = NULL; pcf_app_t *app_session = NULL; OpenAPI_sm_policy_delete_data_t *SmPolicyDeleteData = NULL; ogs_assert(sess); - pcf_ue = pcf_ue_find_by_id(sess->pcf_ue_id); + pcf_ue_sm = pcf_ue_sm_find_by_id(sess->pcf_ue_sm_id); ogs_assert(stream); ogs_assert(message); SmPolicyDeleteData = message->SmPolicyDeleteData; if (!SmPolicyDeleteData) { strerror = ogs_msprintf("[%s:%d] No SmPolicyDeleteData", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } @@ -567,7 +581,7 @@ bool pcf_npcf_smpolicycontrol_handle_delete(pcf_sess_t *sess, } if (pcf_sessions_number_by_snssai_and_dnn( - pcf_ue, &sess->s_nssai, sess->dnn) > 1) { + pcf_ue_sm, &sess->s_nssai, sess->dnn) > 1) { ogs_expect(true == ogs_sbi_send_response(stream, OGS_SBI_HTTP_STATUS_NO_CONTENT)); } else if (sess->binding.resource_uri) { @@ -601,7 +615,7 @@ bool pcf_npcf_policyauthorization_handle_create(pcf_sess_t *sess, bool rc; int i, j, rv, status = 0; char *strerror = NULL; - pcf_ue_t *pcf_ue = NULL; + pcf_ue_sm_t *pcf_ue_sm = NULL; pcf_app_t *app_session = NULL; ogs_sbi_client_t *client = NULL; @@ -649,7 +663,7 @@ bool pcf_npcf_policyauthorization_handle_create(pcf_sess_t *sess, OpenAPI_lnode_t *node = NULL, *node2 = NULL, *node3 = NULL; ogs_assert(sess); - pcf_ue = pcf_ue_find_by_id(sess->pcf_ue_id); + pcf_ue_sm = pcf_ue_sm_find_by_id(sess->pcf_ue_sm_id); ogs_assert(stream); ogs_assert(recvmsg); @@ -662,7 +676,7 @@ bool pcf_npcf_policyauthorization_handle_create(pcf_sess_t *sess, AppSessionContext = recvmsg->AppSessionContext; if (!AppSessionContext) { strerror = ogs_msprintf("[%s:%d] No AppSessionContext", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } @@ -670,28 +684,28 @@ bool pcf_npcf_policyauthorization_handle_create(pcf_sess_t *sess, AscReqData = AppSessionContext->asc_req_data; if (!AscReqData) { strerror = ogs_msprintf("[%s:%d] No AscReqData", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } if (!AscReqData->supp_feat) { strerror = ogs_msprintf("[%s:%d] No AscReqData->suppFeat", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } if (!AscReqData->notif_uri) { strerror = ogs_msprintf("[%s:%d] No AscReqData->notifUri", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } if (!AscReqData->med_components) { strerror = ogs_msprintf("[%s:%d] No AscReqData->MediaCompoenent", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } @@ -700,7 +714,7 @@ bool pcf_npcf_policyauthorization_handle_create(pcf_sess_t *sess, AscReqData->notif_uri); if (rc == false || scheme == OpenAPI_uri_scheme_NULL) { strerror = ogs_msprintf("[%s:%d] Invalid URI [%s]", - pcf_ue->supi, sess->psi, AscReqData->notif_uri); + pcf_ue_sm->supi, sess->psi, AscReqData->notif_uri); status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } @@ -833,12 +847,12 @@ bool pcf_npcf_policyauthorization_handle_create(pcf_sess_t *sess, ogs_freeaddrinfo(addr6); rv = pcf_db_qos_data( - pcf_ue->supi, + pcf_ue_sm->supi, sess->home.presence == true ? &sess->home.plmn_id : NULL, &sess->s_nssai, sess->dnn, &session_data); if (rv != OGS_OK) { strerror = ogs_msprintf("[%s:%d] Cannot find SUPI in DB", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_NOT_FOUND; goto cleanup; } @@ -861,7 +875,7 @@ bool pcf_npcf_policyauthorization_handle_create(pcf_sess_t *sess, if (media_component->media_type == OpenAPI_media_type_NULL) { strerror = ogs_msprintf("[%s:%d] Media-Type is Required", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } @@ -878,7 +892,7 @@ bool pcf_npcf_policyauthorization_handle_create(pcf_sess_t *sess, break; default: strerror = ogs_msprintf("[%s:%d] Unknown Media-Type [%d]", - pcf_ue->supi, sess->psi, media_component->media_type); + pcf_ue_sm->supi, sess->psi, media_component->media_type); status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } @@ -901,7 +915,7 @@ bool pcf_npcf_policyauthorization_handle_create(pcf_sess_t *sess, strerror = ogs_msprintf("[%s:%d] CHECK WEBUI : " "Even the Default Bearer(QCI:%d,ARP:%d) " "cannot support IMS signalling.", - pcf_ue->supi, sess->psi, + pcf_ue_sm->supi, sess->psi, session_data.session.qos.index, session_data.session.qos.arp.priority_level); status = OGS_SBI_HTTP_STATUS_FORBIDDEN; @@ -915,7 +929,7 @@ bool pcf_npcf_policyauthorization_handle_create(pcf_sess_t *sess, strerror = ogs_msprintf("[%s:%d] CHECK WEBUI : " "No PCC Rule in DB [QoS Index:%d] - " "Please add PCC Rule using WEBUI", - pcf_ue->supi, sess->psi, qos_index); + pcf_ue_sm->supi, sess->psi, qos_index); status = OGS_SBI_HTTP_STATUS_FORBIDDEN; goto cleanup; } @@ -946,7 +960,7 @@ bool pcf_npcf_policyauthorization_handle_create(pcf_sess_t *sess, pcc_rule, media_component); if (rv != OGS_OK) { strerror = ogs_msprintf("[%s:%d] install_flow() failed", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_FORBIDDEN; goto cleanup; } @@ -961,7 +975,7 @@ bool pcf_npcf_policyauthorization_handle_create(pcf_sess_t *sess, pcc_rule, media_component); if (count == -1) { strerror = ogs_msprintf("[%s:%d] matched_flow() failed", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_FORBIDDEN; goto cleanup; } @@ -973,7 +987,7 @@ bool pcf_npcf_policyauthorization_handle_create(pcf_sess_t *sess, pcc_rule, media_component); if (rv != OGS_OK) { strerror = ogs_msprintf("[%s:%d] re-install_flow() failed", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_FORBIDDEN; goto cleanup; } @@ -984,7 +998,7 @@ bool pcf_npcf_policyauthorization_handle_create(pcf_sess_t *sess, rv = ogs_pcc_rule_update_qos_from_media(pcc_rule, media_component); if (rv != OGS_OK) { strerror = ogs_msprintf("[%s:%d] update_qos() failed", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_FORBIDDEN; goto cleanup; } @@ -1119,7 +1133,7 @@ bool pcf_npcf_policyauthorization_handle_update( { int i, j, rv, status = 0; char *strerror = NULL; - pcf_ue_t *pcf_ue = NULL; + pcf_ue_sm_t *pcf_ue_sm = NULL; OpenAPI_app_session_context_update_data_patch_t *AppSessionContextUpdateDataPatch = NULL; @@ -1157,7 +1171,7 @@ bool pcf_npcf_policyauthorization_handle_update( OpenAPI_lnode_t *node = NULL, *node2 = NULL, *node3 = NULL; ogs_assert(sess); - pcf_ue = pcf_ue_find_by_id(sess->pcf_ue_id); + pcf_ue_sm = pcf_ue_sm_find_by_id(sess->pcf_ue_sm_id); ogs_assert(app_session); ogs_assert(stream); ogs_assert(recvmsg); @@ -1169,7 +1183,7 @@ bool pcf_npcf_policyauthorization_handle_update( recvmsg->AppSessionContextUpdateDataPatch; if (!AppSessionContextUpdateDataPatch) { strerror = ogs_msprintf("[%s:%d] No AppSessionContextUpdateDataPatch", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } @@ -1177,14 +1191,14 @@ bool pcf_npcf_policyauthorization_handle_update( AscUpdateData = AppSessionContextUpdateDataPatch->asc_req_data; if (!AscUpdateData) { strerror = ogs_msprintf("[%s:%d] No AscUpdateData", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } if (!AscUpdateData->med_components) { strerror = ogs_msprintf("[%s:%d] No AscUpdateData->MediaCompoenent", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } @@ -1281,12 +1295,12 @@ bool pcf_npcf_policyauthorization_handle_update( } rv = pcf_db_qos_data( - pcf_ue->supi, + pcf_ue_sm->supi, sess->home.presence == true ? &sess->home.plmn_id : NULL, &sess->s_nssai, sess->dnn, &session_data); if (rv != OGS_OK) { strerror = ogs_msprintf("[%s:%d] Cannot find SUPI in DB", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_NOT_FOUND; goto cleanup; } @@ -1309,7 +1323,7 @@ bool pcf_npcf_policyauthorization_handle_update( if (media_component->media_type == OpenAPI_media_type_NULL) { strerror = ogs_msprintf("[%s:%d] Media-Type is Required", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } @@ -1326,7 +1340,7 @@ bool pcf_npcf_policyauthorization_handle_update( break; default: strerror = ogs_msprintf("[%s:%d] Unknown Media-Type [%d]", - pcf_ue->supi, sess->psi, media_component->media_type); + pcf_ue_sm->supi, sess->psi, media_component->media_type); status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } @@ -1349,7 +1363,7 @@ bool pcf_npcf_policyauthorization_handle_update( strerror = ogs_msprintf("[%s:%d] CHECK WEBUI : " "Even the Default Bearer(QCI:%d,ARP:%d) " "cannot support IMS signalling.", - pcf_ue->supi, sess->psi, + pcf_ue_sm->supi, sess->psi, session_data.session.qos.index, session_data.session.qos.arp.priority_level); status = OGS_SBI_HTTP_STATUS_FORBIDDEN; @@ -1363,7 +1377,7 @@ bool pcf_npcf_policyauthorization_handle_update( strerror = ogs_msprintf("[%s:%d] CHECK WEBUI : " "No PCC Rule in DB [QoS Index:%d] - " "Please add PCC Rule using WEBUI", - pcf_ue->supi, sess->psi, qos_index); + pcf_ue_sm->supi, sess->psi, qos_index); status = OGS_SBI_HTTP_STATUS_FORBIDDEN; goto cleanup; } @@ -1393,7 +1407,7 @@ bool pcf_npcf_policyauthorization_handle_update( pcc_rule, media_component); if (rv != OGS_OK) { strerror = ogs_msprintf("[%s:%d] install_flow() failed", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_FORBIDDEN; goto cleanup; } @@ -1408,7 +1422,7 @@ bool pcf_npcf_policyauthorization_handle_update( pcc_rule, media_component); if (count == -1) { strerror = ogs_msprintf("[%s:%d] matched_flow() failed", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_FORBIDDEN; goto cleanup; } @@ -1420,7 +1434,7 @@ bool pcf_npcf_policyauthorization_handle_update( pcc_rule, media_component); if (rv != OGS_OK) { strerror = ogs_msprintf("[%s:%d] re-install_flow() failed", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_FORBIDDEN; goto cleanup; } @@ -1431,7 +1445,7 @@ bool pcf_npcf_policyauthorization_handle_update( rv = ogs_pcc_rule_update_qos_from_media(pcc_rule, media_component); if (rv != OGS_OK) { strerror = ogs_msprintf("[%s:%d] update_qos() failed", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_FORBIDDEN; goto cleanup; } diff --git a/src/pcf/npcf-handler.h b/src/pcf/npcf-handler.h index b0f1ddc5f..e03a2270f 100644 --- a/src/pcf/npcf-handler.h +++ b/src/pcf/npcf-handler.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019,2020 by Sukchan Lee + * Copyright (C) 2019-2025 by Sukchan Lee * * This file is part of Open5GS. * @@ -26,7 +26,7 @@ extern "C" { #endif -bool pcf_npcf_am_policy_control_handle_create(pcf_ue_t *pcf_ue, +bool pcf_npcf_am_policy_control_handle_create(pcf_ue_am_t *pcf_ue_am, ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg); bool pcf_npcf_smpolicycontrol_handle_create(pcf_sess_t *sess, diff --git a/src/pcf/nudr-build.c b/src/pcf/nudr-build.c index 4a96994ab..342d33e76 100644 --- a/src/pcf/nudr-build.c +++ b/src/pcf/nudr-build.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 by Sukchan Lee + * Copyright (C) 2019-2025 by Sukchan Lee * * This file is part of Open5GS. * @@ -20,12 +20,12 @@ #include "nudr-build.h" ogs_sbi_request_t *pcf_nudr_dr_build_query_am_data( - pcf_ue_t *pcf_ue, void *data) + pcf_ue_am_t *pcf_ue_am, void *data) { ogs_sbi_message_t message; ogs_sbi_request_t *request = NULL; - ogs_assert(pcf_ue); + ogs_assert(pcf_ue_am); memset(&message, 0, sizeof(message)); message.h.method = (char *)OGS_SBI_HTTP_METHOD_GET; @@ -33,7 +33,7 @@ ogs_sbi_request_t *pcf_nudr_dr_build_query_am_data( message.h.api.version = (char *)OGS_SBI_API_V1; message.h.resource.component[0] = (char *)OGS_SBI_RESOURCE_NAME_POLICY_DATA; message.h.resource.component[1] = (char *)OGS_SBI_RESOURCE_NAME_UES; - message.h.resource.component[2] = pcf_ue->supi; + message.h.resource.component[2] = pcf_ue_am->supi; message.h.resource.component[3] = (char *)OGS_SBI_RESOURCE_NAME_AM_DATA; request = ogs_sbi_build_request(&message); @@ -45,14 +45,14 @@ ogs_sbi_request_t *pcf_nudr_dr_build_query_am_data( ogs_sbi_request_t *pcf_nudr_dr_build_query_sm_data( pcf_sess_t *sess, void *data) { - pcf_ue_t *pcf_ue = NULL; + pcf_ue_sm_t *pcf_ue_sm = NULL; ogs_sbi_message_t message; ogs_sbi_request_t *request = NULL; ogs_assert(sess); - pcf_ue = pcf_ue_find_by_id(sess->pcf_ue_id); - ogs_assert(pcf_ue); + pcf_ue_sm = pcf_ue_sm_find_by_id(sess->pcf_ue_sm_id); + ogs_assert(pcf_ue_sm); memset(&message, 0, sizeof(message)); message.h.method = (char *)OGS_SBI_HTTP_METHOD_GET; @@ -60,7 +60,7 @@ ogs_sbi_request_t *pcf_nudr_dr_build_query_sm_data( message.h.api.version = (char *)OGS_SBI_API_V1; message.h.resource.component[0] = (char *)OGS_SBI_RESOURCE_NAME_POLICY_DATA; message.h.resource.component[1] = (char *)OGS_SBI_RESOURCE_NAME_UES; - message.h.resource.component[2] = pcf_ue->supi; + message.h.resource.component[2] = pcf_ue_sm->supi; message.h.resource.component[3] = (char *)OGS_SBI_RESOURCE_NAME_SM_DATA; message.param.snssai_presence = true; diff --git a/src/pcf/nudr-build.h b/src/pcf/nudr-build.h index 1f15e701b..9e3988e40 100644 --- a/src/pcf/nudr-build.h +++ b/src/pcf/nudr-build.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 by Sukchan Lee + * Copyright (C) 2019-2025 by Sukchan Lee * * This file is part of Open5GS. * @@ -27,7 +27,7 @@ extern "C" { #endif ogs_sbi_request_t *pcf_nudr_dr_build_query_am_data( - pcf_ue_t *pcf_ue, void *data); + pcf_ue_am_t *pcf_ue_am, void *data); ogs_sbi_request_t *pcf_nudr_dr_build_query_sm_data( pcf_sess_t *sess, void *data); diff --git a/src/pcf/nudr-handler.c b/src/pcf/nudr-handler.c index be9c691b2..85ef99c77 100644 --- a/src/pcf/nudr-handler.c +++ b/src/pcf/nudr-handler.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019,2020 by Sukchan Lee + * Copyright (C) 2019-2025 by Sukchan Lee * * This file is part of Open5GS. * @@ -22,7 +22,8 @@ #include "nudr-handler.h" bool pcf_nudr_dr_handle_query_am_data( - pcf_ue_t *pcf_ue, ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg) + pcf_ue_am_t *pcf_ue_am, + ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg) { int rv, status = 0; char *strerror = NULL; @@ -34,7 +35,7 @@ bool pcf_nudr_dr_handle_query_am_data( ogs_subscription_data_t subscription_data; - ogs_assert(pcf_ue); + ogs_assert(pcf_ue_am); ogs_assert(stream); server = ogs_sbi_server_from_stream(stream); ogs_assert(server); @@ -51,52 +52,52 @@ bool pcf_nudr_dr_handle_query_am_data( OpenAPI_lnode_t *node = NULL; if (!recvmsg->AmPolicyData) { - strerror = ogs_msprintf("[%s] No AmPolicyData", pcf_ue->supi); + strerror = ogs_msprintf("[%s] No AmPolicyData", pcf_ue_am->supi); status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } - if (!pcf_ue->policy_association_request) { + if (!pcf_ue_am->policy_association_request) { strerror = ogs_msprintf("[%s] No PolicyAssociationRequest", - pcf_ue->supi); + pcf_ue_am->supi); status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } - rv = ogs_dbi_subscription_data(pcf_ue->supi, &subscription_data); + rv = ogs_dbi_subscription_data(pcf_ue_am->supi, &subscription_data); if (rv != OGS_OK) { strerror = ogs_msprintf("[%s] Cannot find SUPI in DB", - pcf_ue->supi); + pcf_ue_am->supi); status = OGS_SBI_HTTP_STATUS_NOT_FOUND; goto cleanup; } if (!subscription_data.ambr.uplink && !subscription_data.ambr.downlink) { - strerror = ogs_msprintf("[%s] No UE-AMBR", pcf_ue->supi); + strerror = ogs_msprintf("[%s] No UE-AMBR", pcf_ue_am->supi); status = OGS_SBI_HTTP_STATUS_NOT_FOUND; goto cleanup; } memset(&PolicyAssociation, 0, sizeof(PolicyAssociation)); - PolicyAssociation.request = pcf_ue->policy_association_request; + PolicyAssociation.request = pcf_ue_am->policy_association_request; PolicyAssociation.supp_feat = - ogs_uint64_to_string(pcf_ue->am_policy_control_features); + ogs_uint64_to_string(pcf_ue_am->am_policy_control_features); ogs_assert(PolicyAssociation.supp_feat); TriggerList = OpenAPI_list_create(); ogs_assert(TriggerList); memset(&UeAmbr, 0, sizeof(UeAmbr)); - if (OGS_SBI_FEATURES_IS_SET(pcf_ue->am_policy_control_features, + if (OGS_SBI_FEATURES_IS_SET(pcf_ue_am->am_policy_control_features, OGS_SBI_NPCF_AM_POLICY_CONTROL_UE_AMBR_AUTHORIZATION)) { - if (pcf_ue->subscribed_ue_ambr) { + if (pcf_ue_am->subscribed_ue_ambr) { ogs_bitrate_t subscribed_ue_ambr; subscribed_ue_ambr.uplink = ogs_sbi_bitrate_from_string( - pcf_ue->subscribed_ue_ambr->uplink); + pcf_ue_am->subscribed_ue_ambr->uplink); subscribed_ue_ambr.downlink = ogs_sbi_bitrate_from_string( - pcf_ue->subscribed_ue_ambr->downlink); + pcf_ue_am->subscribed_ue_ambr->downlink); if (((subscribed_ue_ambr.uplink / 1000) != (subscription_data.ambr.uplink / 1000)) || @@ -124,7 +125,7 @@ bool pcf_nudr_dr_handle_query_am_data( header.api.version = (char *)OGS_SBI_API_V1; header.resource.component[0] = (char *)OGS_SBI_RESOURCE_NAME_POLICIES; - header.resource.component[1] = pcf_ue->association_id; + header.resource.component[1] = pcf_ue_am->association_id; memset(&sendmsg, 0, sizeof(sendmsg)); sendmsg.PolicyAssociation = &PolicyAssociation; @@ -148,17 +149,18 @@ bool pcf_nudr_dr_handle_query_am_data( ogs_subscription_data_free(&subscription_data); - OpenAPI_list_for_each(PolicyAssociation.request->allowed_snssais, node) { + OpenAPI_list_for_each( + PolicyAssociation.request->allowed_snssais, node) { struct OpenAPI_snssai_s *Snssai = node->data; if (Snssai) { ogs_s_nssai_t s_nssai; s_nssai.sst = Snssai->sst; s_nssai.sd = ogs_s_nssai_sd_from_string(Snssai->sd); - pcf_metrics_inst_by_slice_add(&pcf_ue->guami.plmn_id, + pcf_metrics_inst_by_slice_add(&pcf_ue_am->guami.plmn_id, &s_nssai, PCF_METR_CTR_PA_POLICYAMASSOSUCC, 1); } else { - ogs_error("[%s] No Snssai", pcf_ue->supi); + ogs_error("[%s] No Snssai", pcf_ue_am->supi); } } @@ -166,7 +168,7 @@ bool pcf_nudr_dr_handle_query_am_data( DEFAULT strerror = ogs_msprintf("[%s] Invalid resource name [%s]", - pcf_ue->supi, recvmsg->h.resource.component[3]); + pcf_ue_am->supi, recvmsg->h.resource.component[3]); END cleanup: @@ -188,13 +190,13 @@ bool pcf_nudr_dr_handle_query_sm_data( { int status = 0; char *strerror = NULL; - pcf_ue_t *pcf_ue = NULL; + pcf_ue_sm_t *pcf_ue_sm = NULL; ogs_sbi_server_t *server = NULL; int r; ogs_assert(sess); - pcf_ue = pcf_ue_find_by_id(sess->pcf_ue_id); - ogs_assert(pcf_ue); + pcf_ue_sm = pcf_ue_sm_find_by_id(sess->pcf_ue_sm_id); + ogs_assert(pcf_ue_sm); ogs_assert(stream); server = ogs_sbi_server_from_stream(stream); ogs_assert(server); @@ -205,7 +207,7 @@ bool pcf_nudr_dr_handle_query_sm_data( CASE(OGS_SBI_RESOURCE_NAME_SM_DATA) if (!recvmsg->SmPolicyData) { strerror = ogs_msprintf("[%s:%d] No SmPolicyData", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } @@ -221,7 +223,8 @@ bool pcf_nudr_dr_handle_query_sm_data( DEFAULT strerror = ogs_msprintf("[%s:%d] Invalid resource name [%s]", - pcf_ue->supi, sess->psi, recvmsg->h.resource.component[3]); + pcf_ue_sm->supi, sess->psi, + recvmsg->h.resource.component[3]); END cleanup: diff --git a/src/pcf/nudr-handler.h b/src/pcf/nudr-handler.h index a79d56697..d6162c15f 100644 --- a/src/pcf/nudr-handler.h +++ b/src/pcf/nudr-handler.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019,2020 by Sukchan Lee + * Copyright (C) 2019-2025 by Sukchan Lee * * This file is part of Open5GS. * @@ -27,7 +27,8 @@ extern "C" { #endif bool pcf_nudr_dr_handle_query_am_data( - pcf_ue_t *pcf_ue, ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg); + pcf_ue_am_t *pcf_ue_am, + ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg); bool pcf_nudr_dr_handle_query_sm_data( pcf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg); diff --git a/src/pcf/pcf-sm.c b/src/pcf/pcf-sm.c index 3af52fb18..7226d500f 100644 --- a/src/pcf/pcf-sm.c +++ b/src/pcf/pcf-sm.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019-2024 by Sukchan Lee + * Copyright (C) 2019-2025 by Sukchan Lee * * This file is part of Open5GS. * @@ -53,8 +53,9 @@ void pcf_state_operational(ogs_fsm_t *s, pcf_event_t *e) ogs_sbi_service_type_e service_type = OGS_SBI_SERVICE_TYPE_NULL; - pcf_ue_t *pcf_ue = NULL; - ogs_pool_id_t pcf_ue_id = OGS_INVALID_POOL_ID; + pcf_ue_am_t *pcf_ue_am = NULL; + ogs_pool_id_t pcf_ue_am_id = OGS_INVALID_POOL_ID; + pcf_ue_sm_t *pcf_ue_sm = NULL; pcf_sess_t *sess = NULL; ogs_pool_id_t sess_id = OGS_INVALID_POOL_ID; pcf_app_t *app_session = NULL; @@ -140,18 +141,18 @@ void pcf_state_operational(ogs_fsm_t *s, pcf_event_t *e) CASE(OGS_SBI_HTTP_METHOD_POST) if (message.PolicyAssociationRequest && message.PolicyAssociationRequest->supi) { - pcf_ue = pcf_ue_find_by_supi( + pcf_ue_am = pcf_ue_am_find_by_supi( message.PolicyAssociationRequest->supi); - if (!pcf_ue) { - pcf_ue = pcf_ue_add( + if (!pcf_ue_am) { + pcf_ue_am = pcf_ue_am_add( message.PolicyAssociationRequest->supi); - ogs_assert(pcf_ue); + ogs_assert(pcf_ue_am); } } break; CASE(OGS_SBI_HTTP_METHOD_DELETE) if (message.h.resource.component[1]) { - pcf_ue = pcf_ue_find_by_association_id( + pcf_ue_am = pcf_ue_am_find_by_association_id( message.h.resource.component[1]); } else { ogs_error("No Policy Association Id"); @@ -160,7 +161,7 @@ void pcf_state_operational(ogs_fsm_t *s, pcf_event_t *e) DEFAULT END - if (!pcf_ue) { + if (!pcf_ue_am) { ogs_error("Not found [%s]", message.h.method); ogs_assert(true == ogs_sbi_server_send_error(stream, @@ -169,17 +170,17 @@ void pcf_state_operational(ogs_fsm_t *s, pcf_event_t *e) break; } - ogs_assert(OGS_FSM_STATE(&pcf_ue->sm)); + ogs_assert(OGS_FSM_STATE(&pcf_ue_am->sm)); - e->pcf_ue_id = pcf_ue->id; + e->pcf_ue_am_id = pcf_ue_am->id; e->h.sbi.message = &message; - ogs_fsm_dispatch(&pcf_ue->sm, e); - if (OGS_FSM_CHECK(&pcf_ue->sm, pcf_am_state_exception)) { - ogs_error("[%s] State machine exception", pcf_ue->supi); - pcf_ue_remove(pcf_ue); - } else if (OGS_FSM_CHECK(&pcf_ue->sm, pcf_am_state_deleted)) { - ogs_debug("[%s] PCF-AM removed", pcf_ue->supi); - pcf_ue_remove(pcf_ue); + ogs_fsm_dispatch(&pcf_ue_am->sm, e); + if (OGS_FSM_CHECK(&pcf_ue_am->sm, pcf_am_state_exception)) { + ogs_error("[%s] State machine exception", pcf_ue_am->supi); + pcf_ue_am_remove(pcf_ue_am); + } else if (OGS_FSM_CHECK(&pcf_ue_am->sm, pcf_am_state_deleted)) { + ogs_debug("[%s] PCF-AM removed", pcf_ue_am->supi); + pcf_ue_am_remove(pcf_ue_am); } break; @@ -191,14 +192,14 @@ void pcf_state_operational(ogs_fsm_t *s, pcf_event_t *e) message.SmPolicyContextData->supi && message.SmPolicyContextData->pdu_session_id) { - pcf_ue = pcf_ue_find_by_supi( + pcf_ue_sm = pcf_ue_sm_find_by_supi( message.SmPolicyContextData->supi); - if (!pcf_ue) { + if (!pcf_ue_sm) { if (!strcmp(message.h.method, OGS_SBI_HTTP_METHOD_POST)) { - pcf_ue = pcf_ue_add( + pcf_ue_sm = pcf_ue_sm_add( message.SmPolicyContextData->supi); - if (!pcf_ue) { + if (!pcf_ue_sm) { ogs_error("[%s:%d] Invalid Request [%s]", message.SmPolicyContextData->supi, message.SmPolicyContextData-> @@ -218,13 +219,13 @@ void pcf_state_operational(ogs_fsm_t *s, pcf_event_t *e) } } - if (pcf_ue) { - sess = pcf_sess_find_by_psi(pcf_ue, message. + if (pcf_ue_sm) { + sess = pcf_sess_find_by_psi(pcf_ue_sm, message. SmPolicyContextData->pdu_session_id); if (!sess) { if (!strcmp(message.h.method, OGS_SBI_HTTP_METHOD_POST)) { - sess = pcf_sess_add(pcf_ue, message. + sess = pcf_sess_add(pcf_ue_sm, message. SmPolicyContextData->pdu_session_id); if (!sess) { ogs_error("[%s:%d] " @@ -236,7 +237,7 @@ void pcf_state_operational(ogs_fsm_t *s, pcf_event_t *e) message.h.method); } else ogs_debug("[%s:%d] PCF session added", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); } else { ogs_error("[%s:%d] " "Invalid HTTP method [%s]", @@ -258,15 +259,15 @@ void pcf_state_operational(ogs_fsm_t *s, pcf_event_t *e) END if (!sess) { ogs_error("Not found [%s]", message.h.uri); - /* - * TS29.512 - * 4.2.2.2 SM Policy Association establishment - * - * If the user information received within the "supi" attribute is - * unknown, the PCF shall reject the request with an HTTP "400 Bad - * Request" response message including the "cause" attribute - * of the ProblemDetails data structure set to "USER_UNKNOWN". - */ + /* + * TS29.512 + * 4.2.2.2 SM Policy Association establishment + * + * If the user information received within the "supi" attribute is + * unknown, the PCF shall reject the request with an HTTP "400 Bad + * Request" response message including the "cause" attribute + * of the ProblemDetails data structure set to "USER_UNKNOWN". + */ ogs_assert(true == ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, @@ -280,10 +281,11 @@ void pcf_state_operational(ogs_fsm_t *s, pcf_event_t *e) e->h.sbi.message = &message; ogs_fsm_dispatch(&sess->sm, e); if (OGS_FSM_CHECK(&sess->sm, pcf_sm_state_exception)) { - /* Clang scan-build SA: NULL pointer dereference: pcf_ue=NULL, remove logging of pcf_ue->supi. */ + /* Clang scan-build SA: NULL pointer dereference: + * pcf_ue_sm=NULL, remove logging of pcf_ue_sm->supi. */ ogs_error("[%s:%d] State machine exception", - pcf_ue ? pcf_ue->supi : "Unknown", sess->psi); - pcf_sess_remove(sess); + pcf_ue_sm ? pcf_ue_sm->supi : "Unknown", sess->psi); + PCF_SESS_CLEAR(sess); } break; @@ -332,10 +334,11 @@ void pcf_state_operational(ogs_fsm_t *s, pcf_event_t *e) e->h.sbi.message = &message; ogs_fsm_dispatch(&sess->sm, e); if (OGS_FSM_CHECK(&sess->sm, pcf_sm_state_exception)) { - /* Clang scan-build SA: NULL pointer dereference: pcf_ue=NULL, remove logging of pcf_ue->supi. */ + /* Clang scan-build SA: NULL pointer dereference: + * pcf_ue_sm=NULL, remove logging of pcf_ue_sm->supi. */ ogs_error("[%s:%d] State machine exception", - pcf_ue ? pcf_ue->supi : "Unknown", sess->psi); - pcf_sess_remove(sess); + pcf_ue_sm ? pcf_ue_sm->supi : "Unknown", sess->psi); + PCF_SESS_CLEAR(sess); } break; @@ -496,9 +499,9 @@ void pcf_state_operational(ogs_fsm_t *s, pcf_event_t *e) break; } - pcf_ue_id = sbi_xact->sbi_object_id; - ogs_assert(pcf_ue_id >= OGS_MIN_POOL_ID && - pcf_ue_id <= OGS_MAX_POOL_ID); + pcf_ue_am_id = sbi_xact->sbi_object_id; + ogs_assert(pcf_ue_am_id >= OGS_MIN_POOL_ID && + pcf_ue_am_id <= OGS_MAX_POOL_ID); if (sbi_xact->assoc_stream_id >= OGS_MIN_POOL_ID && sbi_xact->assoc_stream_id <= OGS_MAX_POOL_ID) @@ -507,20 +510,21 @@ void pcf_state_operational(ogs_fsm_t *s, pcf_event_t *e) ogs_sbi_xact_remove(sbi_xact); - pcf_ue = pcf_ue_find_by_id(pcf_ue_id); - if (!pcf_ue) { - ogs_error("UE(pcf_ue) Context " + pcf_ue_am = pcf_ue_am_find_by_id(pcf_ue_am_id); + if (!pcf_ue_am) { + ogs_error("UE(pcf_ue_am) Context " "has already been removed"); break; } - e->pcf_ue_id = pcf_ue->id; + e->pcf_ue_am_id = pcf_ue_am->id; e->h.sbi.message = &message; - ogs_fsm_dispatch(&pcf_ue->sm, e); - if (OGS_FSM_CHECK(&pcf_ue->sm, pcf_am_state_exception)) { - ogs_error("[%s] State machine exception", pcf_ue->supi); - pcf_ue_remove(pcf_ue); + ogs_fsm_dispatch(&pcf_ue_am->sm, e); + if (OGS_FSM_CHECK(&pcf_ue_am->sm, pcf_am_state_exception)) { + ogs_error("[%s] State machine exception", + pcf_ue_am->supi); + pcf_ue_am_remove(pcf_ue_am); } break; @@ -556,8 +560,8 @@ void pcf_state_operational(ogs_fsm_t *s, pcf_event_t *e) break; } - pcf_ue = pcf_ue_find_by_id(sess->pcf_ue_id); - ogs_assert(pcf_ue); + pcf_ue_sm = pcf_ue_sm_find_by_id(sess->pcf_ue_sm_id); + ogs_assert(pcf_ue_sm); e->sess_id = sess->id; e->h.sbi.message = &message; @@ -565,8 +569,8 @@ void pcf_state_operational(ogs_fsm_t *s, pcf_event_t *e) ogs_fsm_dispatch(&sess->sm, e); if (OGS_FSM_CHECK(&sess->sm, pcf_sm_state_exception)) { ogs_error("[%s:%d] State machine exception", - pcf_ue->supi, sess->psi); - pcf_sess_remove(sess); + pcf_ue_sm->supi, sess->psi); + PCF_SESS_CLEAR(sess); } break; @@ -607,7 +611,8 @@ void pcf_state_operational(ogs_fsm_t *s, pcf_event_t *e) if (sbi_xact->assoc_stream_id >= OGS_MIN_POOL_ID && sbi_xact->assoc_stream_id <= OGS_MAX_POOL_ID) - e->h.sbi.data = OGS_UINT_TO_POINTER(sbi_xact->assoc_stream_id); + e->h.sbi.data = OGS_UINT_TO_POINTER( + sbi_xact->assoc_stream_id); ogs_sbi_xact_remove(sbi_xact); @@ -617,8 +622,8 @@ void pcf_state_operational(ogs_fsm_t *s, pcf_event_t *e) break; } - pcf_ue = pcf_ue_find_by_id(sess->pcf_ue_id); - ogs_assert(pcf_ue); + pcf_ue_sm = pcf_ue_sm_find_by_id(sess->pcf_ue_sm_id); + ogs_assert(pcf_ue_sm); e->sess_id = sess->id; e->h.sbi.message = &message; @@ -626,12 +631,12 @@ void pcf_state_operational(ogs_fsm_t *s, pcf_event_t *e) ogs_fsm_dispatch(&sess->sm, e); if (OGS_FSM_CHECK(&sess->sm, pcf_sm_state_exception)) { ogs_error("[%s:%d] State machine exception", - pcf_ue->supi, sess->psi); - pcf_sess_remove(sess); + pcf_ue_sm->supi, sess->psi); + PCF_SESS_CLEAR(sess); } else if (OGS_FSM_CHECK(&sess->sm, pcf_sm_state_deleted)) { ogs_debug("[%s:%d] PCF session removed", - pcf_ue->supi, sess->psi); - pcf_sess_remove(sess); + pcf_ue_sm->supi, sess->psi); + PCF_SESS_CLEAR(sess); } break; @@ -754,16 +759,16 @@ void pcf_state_operational(ogs_fsm_t *s, pcf_event_t *e) switch(sbi_object->type) { case OGS_SBI_OBJ_UE_TYPE: - pcf_ue_id = sbi_xact->sbi_object_id; - ogs_assert(pcf_ue_id >= OGS_MIN_POOL_ID && - pcf_ue_id <= OGS_MAX_POOL_ID); + pcf_ue_am_id = sbi_xact->sbi_object_id; + ogs_assert(pcf_ue_am_id >= OGS_MIN_POOL_ID && + pcf_ue_am_id <= OGS_MAX_POOL_ID); - pcf_ue = pcf_ue_find_by_id(pcf_ue_id); - if (!pcf_ue) { - ogs_error("UE(pcf_ue) has already been removed"); + pcf_ue_am = pcf_ue_am_find_by_id(pcf_ue_am_id); + if (!pcf_ue_am) { + ogs_error("UE(pcf_ue_am) has already been removed"); break; } - ogs_error("[%s] Cannot receive SBI message", pcf_ue->supi); + ogs_error("[%s] Cannot receive SBI message", pcf_ue_am->supi); break; case OGS_SBI_OBJ_SESS_TYPE: diff --git a/src/pcf/sbi-path.c b/src/pcf/sbi-path.c index 758e5f91a..bf9444fa3 100644 --- a/src/pcf/sbi-path.c +++ b/src/pcf/sbi-path.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019-2022 by Sukchan Lee + * Copyright (C) 2019-2025 by Sukchan Lee * * This file is part of Open5GS. * @@ -169,23 +169,23 @@ static int pcf_sbi_discover_and_send( return OGS_OK; } -int pcf_ue_sbi_discover_and_send( +int pcf_ue_am_sbi_discover_and_send( ogs_sbi_service_type_e service_type, ogs_sbi_discovery_option_t *discovery_option, - ogs_sbi_request_t *(*build)(pcf_ue_t *pcf_ue, void *data), - pcf_ue_t *pcf_ue, ogs_sbi_stream_t *stream, void *data) + ogs_sbi_request_t *(*build)(pcf_ue_am_t *pcf_ue_am, void *data), + pcf_ue_am_t *pcf_ue_am, ogs_sbi_stream_t *stream, void *data) { int r; r = pcf_sbi_discover_and_send( - pcf_ue->id, &pcf_ue->sbi, service_type, discovery_option, - (ogs_sbi_build_f)build, pcf_ue, stream, data); + pcf_ue_am->id, &pcf_ue_am->sbi, service_type, discovery_option, + (ogs_sbi_build_f)build, pcf_ue_am, stream, data); if (r != OGS_OK) { - ogs_error("pcf_ue_sbi_discover_and_send() failed"); + ogs_error("pcf_ue_am_sbi_discover_and_send() failed"); ogs_assert(true == ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_GATEWAY_TIMEOUT, NULL, - "Cannot discover", pcf_ue->supi, NULL)); + "Cannot discover", pcf_ue_am->supi, NULL)); return r; } @@ -260,17 +260,17 @@ static int client_delete_notify_cb( return OGS_OK; } -bool pcf_sbi_send_am_policy_control_notify(pcf_ue_t *pcf_ue) +bool pcf_sbi_send_am_policy_control_notify(pcf_ue_am_t *pcf_ue_am) { bool rc; ogs_sbi_request_t *request = NULL; ogs_sbi_client_t *client = NULL; - ogs_assert(pcf_ue); - client = pcf_ue->namf.client; + ogs_assert(pcf_ue_am); + client = pcf_ue_am->namf.client; ogs_assert(client); - request = pcf_namf_callback_build_am_policy_control(pcf_ue, NULL); + request = pcf_namf_callback_build_am_policy_control(pcf_ue_am, NULL); if (!request) { ogs_error("pcf_namf_callback_build_am_policy_control() failed"); return false; @@ -290,7 +290,7 @@ bool pcf_sbi_send_smpolicycontrol_create_response( { int i, rv, status = 0; char *strerror = NULL; - pcf_ue_t *pcf_ue = NULL; + pcf_ue_sm_t *pcf_ue_sm = NULL; ogs_sbi_server_t *server = NULL; ogs_sbi_message_t sendmsg; @@ -323,24 +323,24 @@ bool pcf_sbi_send_smpolicycontrol_create_response( OpenAPI_list_t *PolicyCtrlReqTriggers = NULL; ogs_assert(sess); - pcf_ue = pcf_ue_find_by_id(sess->pcf_ue_id); - ogs_assert(pcf_ue); + pcf_ue_sm = pcf_ue_sm_find_by_id(sess->pcf_ue_sm_id); + ogs_assert(pcf_ue_sm); ogs_assert(stream); server = ogs_sbi_server_from_stream(stream); ogs_assert(server); memset(&session_data, 0, sizeof(ogs_session_data_t)); - ogs_assert(pcf_ue->supi); + ogs_assert(pcf_ue_sm->supi); ogs_assert(sess->dnn); rv = pcf_db_qos_data( - pcf_ue->supi, + pcf_ue_sm->supi, sess->home.presence == true ? &sess->home.plmn_id : NULL, &sess->s_nssai, sess->dnn, &session_data); if (rv != OGS_OK) { strerror = ogs_msprintf("[%s:%d] Cannot find SUPI in DB", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_NOT_FOUND; goto cleanup; } @@ -348,20 +348,20 @@ bool pcf_sbi_send_smpolicycontrol_create_response( session = &session_data.session; if (!session->qos.index) { - strerror = ogs_msprintf("[%s:%d] No 5QI", pcf_ue->supi, sess->psi); + strerror = ogs_msprintf("[%s:%d] No 5QI", pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } if (!session->qos.arp.priority_level) { strerror = ogs_msprintf("[%s:%d] No Priority Level", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } if (!session->ambr.uplink && !session->ambr.downlink) { strerror = ogs_msprintf("[%s:%d] No Session-AMBR", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } @@ -599,7 +599,8 @@ bool pcf_sbi_send_smpolicycontrol_create_response( if (SmPolicyDecision.supp_feat) ogs_free(SmPolicyDecision.supp_feat); - pcf_metrics_inst_by_slice_add(&pcf_ue->guami.plmn_id, + pcf_metrics_inst_by_slice_add( + sess->home.presence == true ? &sess->home.plmn_id : NULL, &sess->s_nssai, PCF_METR_CTR_PA_POLICYSMASSOSUCC, 1); OGS_SESSION_DATA_FREE(&session_data); diff --git a/src/pcf/sbi-path.h b/src/pcf/sbi-path.h index b72465964..757c91e6c 100644 --- a/src/pcf/sbi-path.h +++ b/src/pcf/sbi-path.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019-2022 by Sukchan Lee + * Copyright (C) 2019-2025 by Sukchan Lee * * This file is part of Open5GS. * @@ -35,18 +35,18 @@ void pcf_sbi_close(void); bool pcf_sbi_send_request( ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_xact_t *xact); -int pcf_ue_sbi_discover_and_send( +int pcf_ue_am_sbi_discover_and_send( ogs_sbi_service_type_e service_type, ogs_sbi_discovery_option_t *discovery_option, - ogs_sbi_request_t *(*build)(pcf_ue_t *pcf_ue, void *data), - pcf_ue_t *pcf_ue, ogs_sbi_stream_t *stream, void *data); + ogs_sbi_request_t *(*build)(pcf_ue_am_t *pcf_ue_am, void *data), + pcf_ue_am_t *pcf_ue_am, ogs_sbi_stream_t *stream, void *data); int pcf_sess_sbi_discover_and_send( ogs_sbi_service_type_e service_type, ogs_sbi_discovery_option_t *discovery_option, ogs_sbi_request_t *(*build)(pcf_sess_t *sess, void *data), pcf_sess_t *sess, ogs_sbi_stream_t *stream, void *data); -bool pcf_sbi_send_am_policy_control_notify(pcf_ue_t *pcf_ue); +bool pcf_sbi_send_am_policy_control_notify(pcf_ue_am_t *pcf_ue_am); bool pcf_sbi_send_smpolicycontrol_create_response( pcf_sess_t *sess, ogs_sbi_stream_t *stream); bool pcf_sbi_send_smpolicycontrol_update_notify( diff --git a/src/pcf/sm-sm.c b/src/pcf/sm-sm.c index 1693c1af8..dcfa471aa 100644 --- a/src/pcf/sm-sm.c +++ b/src/pcf/sm-sm.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019-2024 by Sukchan Lee + * Copyright (C) 2019-2025 by Sukchan Lee * * This file is part of Open5GS. * @@ -38,7 +38,7 @@ void pcf_sm_state_final(ogs_fsm_t *s, pcf_event_t *e) void pcf_sm_state_operational(ogs_fsm_t *s, pcf_event_t *e) { bool handled; - pcf_ue_t *pcf_ue = NULL; + pcf_ue_sm_t *pcf_ue_sm = NULL; pcf_sess_t *sess = NULL; ogs_sbi_stream_t *stream = NULL; @@ -52,8 +52,8 @@ void pcf_sm_state_operational(ogs_fsm_t *s, pcf_event_t *e) sess = pcf_sess_find_by_id(e->sess_id); ogs_assert(sess); - pcf_ue = pcf_ue_find_by_id(sess->pcf_ue_id); - ogs_assert(pcf_ue); + pcf_ue_sm = pcf_ue_sm_find_by_id(sess->pcf_ue_sm_id); + ogs_assert(pcf_ue_sm); switch (e->h.id) { case OGS_FSM_ENTRY_SIG: @@ -84,7 +84,7 @@ void pcf_sm_state_operational(ogs_fsm_t *s, pcf_event_t *e) if (!handled) { ogs_error("[%s:%d] " "pcf_npcf_smpolicycontrol_handle_create() failed", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); OGS_FSM_TRAN(s, pcf_sm_state_exception); } } else { @@ -95,14 +95,14 @@ void pcf_sm_state_operational(ogs_fsm_t *s, pcf_event_t *e) if (!handled) { ogs_error("[%s:%d] " "pcf_npcf_smpolicycontrol_handle_delete() failed", - pcf_ue->supi, sess->psi); + pcf_ue_sm->supi, sess->psi); OGS_FSM_TRAN(s, pcf_sm_state_exception); } break; DEFAULT ogs_error("[%s:%d] Invalid HTTP URI [%s]", - pcf_ue->supi, sess->psi, message->h.uri); + pcf_ue_sm->supi, sess->psi, message->h.uri); ogs_assert(true == ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_METHOD_NOT_ALLOWED, message, @@ -121,7 +121,7 @@ void pcf_sm_state_operational(ogs_fsm_t *s, pcf_event_t *e) break; DEFAULT ogs_error("[%s:%d] Invalid resource name [%s]", - pcf_ue->supi, sess->psi, + pcf_ue_sm->supi, sess->psi, message->h.resource.component[2]); ogs_assert(true == ogs_sbi_server_send_error(stream, @@ -136,7 +136,7 @@ void pcf_sm_state_operational(ogs_fsm_t *s, pcf_event_t *e) break; DEFAULT ogs_error("[%s:%d] Unknown method [%s]", - pcf_ue->supi, sess->psi, message->h.method); + pcf_ue_sm->supi, sess->psi, message->h.method); ogs_assert(true == ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_METHOD_NOT_ALLOWED, message, @@ -151,7 +151,7 @@ void pcf_sm_state_operational(ogs_fsm_t *s, pcf_event_t *e) break; DEFAULT ogs_error("[%s:%d] Unknown method [%s]", - pcf_ue->supi, sess->psi, message->h.method); + pcf_ue_sm->supi, sess->psi, message->h.method); ogs_assert(true == ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_METHOD_NOT_ALLOWED, message, @@ -162,7 +162,7 @@ void pcf_sm_state_operational(ogs_fsm_t *s, pcf_event_t *e) DEFAULT ogs_error("[%s:%d] Invalid API name [%s]", - pcf_ue->supi, sess->psi, message->h.service.name); + pcf_ue_sm->supi, sess->psi, message->h.service.name); ogs_assert_if_reached(); END break; @@ -192,42 +192,44 @@ void pcf_sm_state_operational(ogs_fsm_t *s, pcf_event_t *e) if (message->res_status == OGS_SBI_HTTP_STATUS_NOT_FOUND) { ogs_warn("[%s:%d] Cannot find SUPI [%d]", - pcf_ue->supi, sess->psi, message->res_status); - /* - * TS29.512 - * 4.2.2.2 SM Policy Association establishment - * - * If the user information received within the "supi" - * attribute is unknown, the PCF shall reject the - * request with an HTTP "400 Bad Request" response - * message including the "cause" attribute of the - * ProblemDetails data structure set to "USER_UNKNOWN". - */ + pcf_ue_sm->supi, + sess->psi, message->res_status); + /* + * TS29.512 + * 4.2.2.2 SM Policy Association establishment + * + * If the user information received within the "supi" + * attribute is unknown, the PCF shall reject the + * request with an HTTP "400 Bad Request" response + * message including the "cause" attribute of the + * ProblemDetails data structure set to "USER_UNKNOWN". + */ ogs_assert(true == ogs_sbi_server_send_error( stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, NULL, "End user is unknown to the PCF", - pcf_ue->supi, "USER_UNKNOWN")); + pcf_ue_sm->supi, "USER_UNKNOWN")); } else { ogs_error("[%s:%d] HTTP response error [%d]", - pcf_ue->supi, sess->psi, message->res_status); - /* - * TS29.512 - * 4.2.2.2 SM Policy Association establishment - * - * If the PCF, based on local configuration and/or - * operator policies, denies the creation of the - * Individual SM Policy resource, the PCF may reject - * the request and include in an HTTP "403 Forbidden" - * response message the "cause" attribute of the - * ProblemDetails data structure set to - * "POLICY_CONTEXT_DENIED". - */ + pcf_ue_sm->supi, + sess->psi, message->res_status); + /* + * TS29.512 + * 4.2.2.2 SM Policy Association establishment + * + * If the PCF, based on local configuration and/or + * operator policies, denies the creation of the + * Individual SM Policy resource, the PCF may reject + * the request and include in an HTTP "403 Forbidden" + * response message the "cause" attribute of the + * ProblemDetails data structure set to + * "POLICY_CONTEXT_DENIED". + */ ogs_assert(true == ogs_sbi_server_send_error( stream, OGS_SBI_HTTP_STATUS_FORBIDDEN, NULL, "HTTP response error", - pcf_ue->supi, "POLICY_CONTEXT_DENIED")); + pcf_ue_sm->supi, "POLICY_CONTEXT_DENIED")); } break; } @@ -237,7 +239,7 @@ void pcf_sm_state_operational(ogs_fsm_t *s, pcf_event_t *e) DEFAULT ogs_error("[%s:%d] Invalid resource name [%s]", - pcf_ue->supi, sess->psi, + pcf_ue_sm->supi, sess->psi, message->h.resource.component[1]); ogs_assert_if_reached(); END @@ -245,7 +247,7 @@ void pcf_sm_state_operational(ogs_fsm_t *s, pcf_event_t *e) DEFAULT ogs_error("[%s:%d] Invalid resource name [%s]", - pcf_ue->supi, sess->psi, + pcf_ue_sm->supi, sess->psi, message->h.resource.component[0]); ogs_assert_if_reached(); END @@ -260,7 +262,7 @@ void pcf_sm_state_operational(ogs_fsm_t *s, pcf_event_t *e) if (message->res_status != OGS_SBI_HTTP_STATUS_NO_CONTENT) { ogs_warn("[%s:%d] HTTP response error [%d]", - pcf_ue->supi, sess->psi, message->res_status); + pcf_ue_sm->supi, sess->psi, message->res_status); /* * The PCfBindings resource for that UE may not exist in the BSF @@ -272,7 +274,8 @@ void pcf_sm_state_operational(ogs_fsm_t *s, pcf_event_t *e) ogs_assert(true == ogs_sbi_server_send_error(stream, message->res_status, - NULL, "HTTP response error", pcf_ue->supi)); + NULL, "HTTP response error", + pcf_ue_sm->supi)); OGS_FSM_TRAN(s, pcf_sm_state_exception); break; #endif @@ -284,7 +287,7 @@ void pcf_sm_state_operational(ogs_fsm_t *s, pcf_event_t *e) break; DEFAULT ogs_error("[%s:%d] Unknown method [%s]", - pcf_ue->supi, sess->psi, message->h.method); + pcf_ue_sm->supi, sess->psi, message->h.method); ogs_assert_if_reached(); END break; @@ -297,7 +300,8 @@ void pcf_sm_state_operational(ogs_fsm_t *s, pcf_event_t *e) sess, stream, message); } else { ogs_error("[%s:%d] HTTP response error [%d]", - pcf_ue->supi, sess->psi, message->res_status); + pcf_ue_sm->supi, + sess->psi, message->res_status); /* * Send Response @@ -310,7 +314,7 @@ void pcf_sm_state_operational(ogs_fsm_t *s, pcf_event_t *e) break; DEFAULT ogs_error("[%s:%d] Unknown method [%s]", - pcf_ue->supi, sess->psi, message->h.method); + pcf_ue_sm->supi, sess->psi, message->h.method); ogs_assert_if_reached(); END } @@ -318,7 +322,7 @@ void pcf_sm_state_operational(ogs_fsm_t *s, pcf_event_t *e) DEFAULT ogs_error("[%s:%d] Invalid resource name [%s]", - pcf_ue->supi, sess->psi, + pcf_ue_sm->supi, sess->psi, message->h.resource.component[0]); ogs_assert_if_reached(); END @@ -326,21 +330,21 @@ void pcf_sm_state_operational(ogs_fsm_t *s, pcf_event_t *e) DEFAULT ogs_error("[%s:%d] Invalid API name [%s]", - pcf_ue->supi, sess->psi, message->h.service.name); + pcf_ue_sm->supi, sess->psi, message->h.service.name); ogs_assert_if_reached(); END break; default: ogs_error("[%s:%d] Unknown event %s", - pcf_ue->supi, sess->psi, pcf_event_get_name(e)); + pcf_ue_sm->supi, sess->psi, pcf_event_get_name(e)); break; } } void pcf_sm_state_deleted(ogs_fsm_t *s, pcf_event_t *e) { - pcf_ue_t *pcf_ue = NULL; + pcf_ue_sm_t *pcf_ue_sm = NULL; pcf_sess_t *sess = NULL; ogs_assert(s); @@ -350,12 +354,13 @@ void pcf_sm_state_deleted(ogs_fsm_t *s, pcf_event_t *e) sess = pcf_sess_find_by_id(e->sess_id); ogs_assert(sess); - pcf_ue = pcf_ue_find_by_id(sess->pcf_ue_id); - ogs_assert(pcf_ue); + pcf_ue_sm = pcf_ue_sm_find_by_id(sess->pcf_ue_sm_id); + ogs_assert(pcf_ue_sm); switch (e->h.id) { case OGS_FSM_ENTRY_SIG: - pcf_metrics_inst_by_slice_add(&pcf_ue->guami.plmn_id, + pcf_metrics_inst_by_slice_add( + sess->home.presence == true ? &sess->home.plmn_id : NULL, &sess->s_nssai, PCF_METR_GAUGE_PA_SESSIONNBR, -1); break; @@ -364,14 +369,14 @@ void pcf_sm_state_deleted(ogs_fsm_t *s, pcf_event_t *e) default: ogs_error("[%s:%d] Unknown event %s", - pcf_ue->supi, sess->psi, pcf_event_get_name(e)); + pcf_ue_sm->supi, sess->psi, pcf_event_get_name(e)); break; } } void pcf_sm_state_exception(ogs_fsm_t *s, pcf_event_t *e) { - pcf_ue_t *pcf_ue = NULL; + pcf_ue_sm_t *pcf_ue_sm = NULL; pcf_sess_t *sess = NULL; ogs_assert(s); @@ -381,12 +386,13 @@ void pcf_sm_state_exception(ogs_fsm_t *s, pcf_event_t *e) sess = pcf_sess_find_by_id(e->sess_id); ogs_assert(sess); - pcf_ue = pcf_ue_find_by_id(sess->pcf_ue_id); - ogs_assert(pcf_ue); + pcf_ue_sm = pcf_ue_sm_find_by_id(sess->pcf_ue_sm_id); + ogs_assert(pcf_ue_sm); switch (e->h.id) { case OGS_FSM_ENTRY_SIG: - pcf_metrics_inst_by_slice_add(&pcf_ue->guami.plmn_id, + pcf_metrics_inst_by_slice_add( + sess->home.presence == true ? &sess->home.plmn_id : NULL, &sess->s_nssai, PCF_METR_GAUGE_PA_SESSIONNBR, -1); break; @@ -395,7 +401,7 @@ void pcf_sm_state_exception(ogs_fsm_t *s, pcf_event_t *e) default: ogs_error("[%s:%d] Unknown event %s", - pcf_ue->supi, sess->psi, pcf_event_get_name(e)); + pcf_ue_sm->supi, sess->psi, pcf_event_get_name(e)); break; } } diff --git a/src/smf/context.c b/src/smf/context.c index 58936215a..4ff1dbb2e 100644 --- a/src/smf/context.c +++ b/src/smf/context.c @@ -1084,6 +1084,9 @@ void smf_ue_remove(smf_ue_t *smf_ue) ogs_free(smf_ue->supi); } + if (smf_ue->gpsi) + ogs_free(smf_ue->gpsi); + if (smf_ue->imsi_len) { ogs_hash_set(self.imsi_hash, smf_ue->imsi, smf_ue->imsi_len, NULL); } diff --git a/src/smf/context.h b/src/smf/context.h index 84c229278..4f48a4de3 100644 --- a/src/smf/context.h +++ b/src/smf/context.h @@ -117,6 +117,9 @@ typedef struct smf_ue_s { /* SUPI */ char *supi; + /* GPSI */ + char *gpsi; + /* IMSI */ uint8_t imsi[OGS_MAX_IMSI_LEN]; int imsi_len; diff --git a/src/smf/npcf-build.c b/src/smf/npcf-build.c index 6110b735e..b7fed3b4d 100644 --- a/src/smf/npcf-build.c +++ b/src/smf/npcf-build.c @@ -75,6 +75,9 @@ ogs_sbi_request_t *smf_npcf_smpolicycontrol_build_create( */ SmPolicyContextData.chargingcharacteristics = (char *)"00000800"; + /* GPSI */ + SmPolicyContextData.gpsi = smf_ue->gpsi; + /* * Use ogs_sbi_supi_in_vplmn() instead of ogs_sbi_plmn_id_in_vplmn(). * This is because some vendors might not use the full DNN in LBO and @@ -287,8 +290,6 @@ ogs_sbi_request_t *smf_npcf_smpolicycontrol_build_create( end: if (SmPolicyContextData.notification_uri) ogs_free(SmPolicyContextData.notification_uri); - if (SmPolicyContextData.gpsi) - ogs_free(SmPolicyContextData.gpsi); if (SmPolicyContextData.dnn) ogs_free(SmPolicyContextData.dnn); diff --git a/src/smf/nsmf-handler.c b/src/smf/nsmf-handler.c index 1f1c32b07..690c39249 100644 --- a/src/smf/nsmf-handler.c +++ b/src/smf/nsmf-handler.c @@ -220,6 +220,10 @@ bool smf_nsmf_handle_create_sm_context( } ogs_free(type); } + + if (smf_ue->gpsi) + ogs_free(smf_ue->gpsi); + smf_ue->gpsi = ogs_strdup(SmContextCreateData->gpsi); } /* Serving PLMN & Home PLMN */ From 3a91d2aa3fd1c1b52dab6a56d554fb1810dddd86 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Fri, 9 May 2025 16:02:06 +0900 Subject: [PATCH 21/22] [SBI] Guard against missing poll.write in session_write_callback to prevent shutdown assertion (#3893, #3807, #2411, #2312) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prior to this change, `session_write_callback()` unconditionally asserted that `sbi_sess->poll.write` was non-NULL when the write queue drained, then removed it from the poll set. In edge cases—particularly when using curl 8.x with external epoll and `SIGPIPE` disabled—a late `EPOLLOUT` or errant write-ready notification could arrive after `poll.write` had already been cleared. This triggered the assertion in `nghttp2-server.c:1765`, aborting the process on shutdown or session teardown. This commit replaces the hard assertion with a runtime guard. If `poll.write` is present, it is removed and reset to NULL as before. If it is already NULL, we emit an warning log (`ogs_warn`) instead of aborting. This ensures any stray write events after cleanup are safely ignored, allowing a clean exit without crashing. - Wrap `ogs_pollset_remove()` and pointer clear in `if (sbi_sess->poll.write)` - Log an warning when `poll.write` is unexpectedly absent - Preserve original behavior when `poll.write` is valid This change resolves the fatal assertion observed on process exit after the EPOLLERR/SIGPIPE fix and improves overall shutdown robustness. --- lib/sbi/nghttp2-server.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/sbi/nghttp2-server.c b/lib/sbi/nghttp2-server.c index 36c8f633f..54d5334a9 100644 --- a/lib/sbi/nghttp2-server.c +++ b/lib/sbi/nghttp2-server.c @@ -1762,9 +1762,12 @@ static void session_write_callback(short when, ogs_socket_t fd, void *data) ogs_assert(sbi_sess); if (ogs_list_empty(&sbi_sess->write_queue) == true) { - ogs_assert(sbi_sess->poll.write); - ogs_pollset_remove(sbi_sess->poll.write); - sbi_sess->poll.write = NULL; + if (sbi_sess->poll.write) { + ogs_pollset_remove(sbi_sess->poll.write); + sbi_sess->poll.write = NULL; + } else + ogs_warn("poll.write has already been removed"); + return; } From 78ea40881c85e266848071391cd36d9172e60a51 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Fri, 9 May 2025 16:47:42 +0900 Subject: [PATCH 22/22] [ipfw2] override errx() to prevent exit on error (#3840) In ipfw2.c errx() would call exit(), aborting the UPF thread on rule parse errors. Add a macro mapping errx() to ogs_log_message() so errors are logged. We no longer call exit() and the main loop continues on error. --- lib/ipfw/ipfw2.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/ipfw/ipfw2.c b/lib/ipfw/ipfw2.c index 2675bf451..682f67ecd 100644 --- a/lib/ipfw/ipfw2.c +++ b/lib/ipfw/ipfw2.c @@ -73,6 +73,10 @@ int resvd_set_number = RESVD_SET; int ipfw_socket = -1; +#if 1 /* modifed by acetcom */ +#define errx(eval, ...) ogs_log_message(OGS_LOG_ERROR, 0, __VA_ARGS__) +#endif + #define CHECK_LENGTH(v, len) do { \ if ((v) < (len)) \ errx(EX_DATAERR, "Rule too long"); \