From 68edcd64381542ef23509008547f1f8f62103434 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Sat, 7 Aug 2021 14:23:20 +0900 Subject: [PATCH] fix the SMF crash when num of flow > 8 (#1108) --- lib/core/ogs-3gpp-types.h | 24 ++++++++++++------ lib/dbi/session.c | 3 ++- lib/gtp/types.c | 6 +++-- lib/gtp/types.h | 2 +- lib/nas/5gs/types.c | 3 ++- lib/nas/5gs/types.h | 2 +- lib/pfcp/build.c | 14 +++++------ lib/pfcp/context.c | 3 ++- lib/pfcp/context.h | 2 +- lib/pfcp/handler.c | 4 +-- src/pcf/npcf-handler.c | 6 ++++- src/pcrf/pcrf-gx-path.c | 11 ++++++--- src/pcrf/pcrf-rx-path.c | 2 ++ src/smf/binding.c | 12 ++++++++- src/smf/context.c | 30 ++++++++++++++++------- src/smf/gsm-build.c | 1 + src/smf/gx-path.c | 51 +++++++++++++++++++++++++++++++++------ src/smf/s5c-handler.c | 9 ++++--- 18 files changed, 134 insertions(+), 51 deletions(-) diff --git a/lib/core/ogs-3gpp-types.h b/lib/core/ogs-3gpp-types.h index fa49aff40..85118cd2d 100644 --- a/lib/core/ogs-3gpp-types.h +++ b/lib/core/ogs-3gpp-types.h @@ -32,11 +32,21 @@ extern "C" { #define OGS_MAX_NUM_OF_BEARER 4 /* Num of Bearer per Session */ #define OGS_MAX_NUM_OF_PACKET_BUFFER 64 /* Num of PacketBuffer per UE */ -/* Num of Flow per Bearer or PCC Rule or PDR */ -#define OGS_MAX_NUM_OF_FLOW 8 - -/* Num of PacketFilter per Bearer(GTP) or QoS(NAS-5GS) */ -#define OGS_MAX_NUM_OF_PACKET_FILTER 16 +/* + * The array of TLV messages is limited to 8. + * So, Flow(PDI.SDF_Filter) in PDR is limited to 8. + * + * However, the number of flow in bearer context seems to need more than 16. + * + * Therefore, the maximum number of flows of messages is defined as 8, + * and the maximum number of flows stored by the context is 16. + */ +#define OGS_MAX_NUM_OF_FLOW_IN_PDR 8 +#define OGS_MAX_NUM_OF_FLOW_IN_GTP OGS_MAX_NUM_OF_FLOW_IN_PDR +#define OGS_MAX_NUM_OF_FLOW_IN_NAS OGS_MAX_NUM_OF_FLOW_IN_PDR +#define OGS_MAX_NUM_OF_FLOW_IN_PCC_RULE OGS_MAX_NUM_OF_FLOW_IN_PDR +#define OGS_MAX_NUM_OF_FLOW_IN_MEDIA_SUB_COMPONENT OGS_MAX_NUM_OF_FLOW_IN_PDR +#define OGS_MAX_NUM_OF_FLOW_IN_BEARER 16 #define OGS_MAX_NUM_OF_GTPU_RESOURCE 4 @@ -339,7 +349,7 @@ typedef struct ogs_pcc_rule_s { char *id; /* 5GC */ char *name; /* EPC */ - ogs_flow_t flow[OGS_MAX_NUM_OF_FLOW]; + ogs_flow_t flow[OGS_MAX_NUM_OF_FLOW_IN_PCC_RULE]; int num_of_flow; int flow_status; @@ -627,7 +637,7 @@ void ogs_session_data_free(ogs_session_data_t *session_data); typedef struct ogs_media_sub_component_s { uint32_t flow_number; uint32_t flow_usage; - ogs_flow_t flow[OGS_MAX_NUM_OF_FLOW]; + ogs_flow_t flow[OGS_MAX_NUM_OF_FLOW_IN_MEDIA_SUB_COMPONENT]; int num_of_flow; } ogs_media_sub_component_t; diff --git a/lib/dbi/session.c b/lib/dbi/session.c index cf302c638..609ecd434 100644 --- a/lib/dbi/session.c +++ b/lib/dbi/session.c @@ -436,7 +436,8 @@ done: while (bson_iter_next(&child7_iter)) { ogs_flow_t *flow = NULL; - ogs_assert(flow_index < OGS_MAX_NUM_OF_FLOW); + ogs_assert( + flow_index < OGS_MAX_NUM_OF_FLOW_IN_PCC_RULE); flow = &pcc_rule->flow[flow_index]; bson_iter_recurse(&child7_iter, &child8_iter); diff --git a/lib/gtp/types.c b/lib/gtp/types.c index ef000d327..38e46abe8 100644 --- a/lib/gtp/types.c +++ b/lib/gtp/types.c @@ -302,7 +302,8 @@ int16_t ogs_gtp_parse_tft(ogs_gtp_tft_t *tft, ogs_tlv_octet_t *octet) tft->code == OGS_GTP_TFT_CODE_DELETE_EXISTING_TFT) return size; - for (i = 0; i < tft->num_of_packet_filter; i++) { + for (i = 0; i < tft->num_of_packet_filter && + i < OGS_MAX_NUM_OF_FLOW_IN_GTP ; i++) { ogs_assert(size+sizeof(tft->pf[i].flags) <= octet->len); memcpy(&tft->pf[i].flags, (unsigned char *)octet->data+size, sizeof(tft->pf[i].flags)); @@ -468,7 +469,8 @@ int16_t ogs_gtp_build_tft( tft->code == OGS_GTP_TFT_CODE_DELETE_EXISTING_TFT) return size; - for (i = 0; i < target.num_of_packet_filter; i++) { + for (i = 0; i < target.num_of_packet_filter && + i < OGS_MAX_NUM_OF_FLOW_IN_GTP; i++) { ogs_assert(size + sizeof(target.pf[i].flags) <= data_len); memcpy((unsigned char *)octet->data + size, &target.pf[i].flags, sizeof(target.pf[i].flags)); diff --git a/lib/gtp/types.h b/lib/gtp/types.h index d188971af..1301a4612 100644 --- a/lib/gtp/types.h +++ b/lib/gtp/types.h @@ -302,7 +302,7 @@ ED3(uint8_t code:3;, }; uint8_t precedence; ogs_pf_content_t content; - } pf[OGS_MAX_NUM_OF_PACKET_FILTER]; + } pf[OGS_MAX_NUM_OF_FLOW_IN_GTP]; } ogs_gtp_tft_t; int16_t ogs_gtp_parse_tft(ogs_gtp_tft_t *tft, ogs_tlv_octet_t *octet); diff --git a/lib/nas/5gs/types.c b/lib/nas/5gs/types.c index 9282f64ff..c00d10c6f 100644 --- a/lib/nas/5gs/types.c +++ b/lib/nas/5gs/types.c @@ -484,7 +484,8 @@ int ogs_nas_build_qos_rules(ogs_nas_qos_rules_t *rules, memcpy(buffer + length, &target.flags, sizeof(target.flags)); length += sizeof(target.flags); - for (j = 0; j < target.num_of_packet_filter; j++) { + for (j = 0; j < target.num_of_packet_filter && + j < OGS_MAX_NUM_OF_FLOW_IN_NAS; j++) { ogs_assert(length + sizeof(target.pf[j].flags) <= OGS_NAS_MAX_QOS_RULES_LEN); memcpy(buffer + length, &target.pf[j].flags, diff --git a/lib/nas/5gs/types.h b/lib/nas/5gs/types.h index 5e01cddf8..e03155b17 100644 --- a/lib/nas/5gs/types.h +++ b/lib/nas/5gs/types.h @@ -837,7 +837,7 @@ typedef struct ogs_nas_qos_rule_s { uint8_t flags; }; ogs_pf_content_t content; - } pf[OGS_MAX_NUM_OF_PACKET_FILTER]; + } pf[OGS_MAX_NUM_OF_FLOW_IN_NAS]; uint8_t precedence; union { diff --git a/lib/pfcp/build.c b/lib/pfcp/build.c index dedc961db..a5a2a42a2 100644 --- a/lib/pfcp/build.c +++ b/lib/pfcp/build.c @@ -238,7 +238,7 @@ ogs_pkbuf_t *ogs_pfcp_up_build_association_setup_response(uint8_t type, static struct { ogs_pfcp_f_teid_t f_teid; char dnn[OGS_MAX_DNN_LEN]; - char *sdf_filter[OGS_MAX_NUM_OF_FLOW]; + char *sdf_filter[OGS_MAX_NUM_OF_FLOW_IN_PDR]; } pdrbuf[OGS_MAX_NUM_OF_PDR]; void ogs_pfcp_pdrbuf_init(void) @@ -250,7 +250,7 @@ void ogs_pfcp_pdrbuf_clear(void) { int i, j; for (i = 0; i < OGS_MAX_NUM_OF_PDR; i++) { - for (j = 0; j < OGS_MAX_NUM_OF_FLOW; j++) { + for (j = 0; j < OGS_MAX_NUM_OF_FLOW_IN_PDR; j++) { if (pdrbuf[i].sdf_filter[j]) ogs_free(pdrbuf[i].sdf_filter[j]); } @@ -261,7 +261,7 @@ void ogs_pfcp_build_create_pdr( ogs_pfcp_tlv_create_pdr_t *message, int i, ogs_pfcp_pdr_t *pdr) { ogs_pfcp_far_t *far = NULL; - ogs_pfcp_sdf_filter_t pfcp_sdf_filter[OGS_MAX_NUM_OF_FLOW]; + ogs_pfcp_sdf_filter_t pfcp_sdf_filter[OGS_MAX_NUM_OF_FLOW_IN_PDR]; int j = 0; int len = 0; @@ -293,8 +293,7 @@ void ogs_pfcp_build_create_pdr( } memset(pfcp_sdf_filter, 0, sizeof(pfcp_sdf_filter)); - ogs_assert(pdr->num_of_flow <= OGS_MAX_NUM_OF_FLOW); - for (j = 0; j < pdr->num_of_flow; j++) { + for (j = 0; j < pdr->num_of_flow && j < OGS_MAX_NUM_OF_FLOW_IN_PDR; j++) { pfcp_sdf_filter[j].fd = 1; pfcp_sdf_filter[j].flow_description_len = strlen(pdr->flow_description[j]); @@ -377,7 +376,7 @@ void ogs_pfcp_build_created_pdr( void ogs_pfcp_build_update_pdr( ogs_pfcp_tlv_update_pdr_t *message, int i, ogs_pfcp_pdr_t *pdr) { - ogs_pfcp_sdf_filter_t pfcp_sdf_filter[OGS_MAX_NUM_OF_FLOW]; + ogs_pfcp_sdf_filter_t pfcp_sdf_filter[OGS_MAX_NUM_OF_FLOW_IN_PDR]; int j = 0; int len = 0; @@ -400,8 +399,7 @@ void ogs_pfcp_build_update_pdr( } memset(pfcp_sdf_filter, 0, sizeof(pfcp_sdf_filter)); - ogs_assert(pdr->num_of_flow <= OGS_MAX_NUM_OF_FLOW); - for (j = 0; j < pdr->num_of_flow; j++) { + for (j = 0; j < pdr->num_of_flow && j < OGS_MAX_NUM_OF_FLOW_IN_PDR; j++) { pfcp_sdf_filter[j].fd = 1; pfcp_sdf_filter[j].flow_description_len = strlen(pdr->flow_description[j]); diff --git a/lib/pfcp/context.c b/lib/pfcp/context.c index 14e4a10a3..55756969b 100644 --- a/lib/pfcp/context.c +++ b/lib/pfcp/context.c @@ -79,7 +79,8 @@ void ogs_pfcp_context_init(void) ogs_app()->pool.sess * OGS_MAX_NUM_OF_BAR); ogs_pool_init(&ogs_pfcp_rule_pool, - ogs_app()->pool.sess * OGS_MAX_NUM_OF_PDR * OGS_MAX_NUM_OF_FLOW); + ogs_app()->pool.sess * + OGS_MAX_NUM_OF_PDR * OGS_MAX_NUM_OF_FLOW_IN_PDR); ogs_pool_init(&ogs_pfcp_dev_pool, OGS_MAX_NUM_OF_DEV); ogs_pool_init(&ogs_pfcp_subnet_pool, OGS_MAX_NUM_OF_SUBNET); diff --git a/lib/pfcp/context.h b/lib/pfcp/context.h index e14ccb03a..e14ef48dc 100644 --- a/lib/pfcp/context.h +++ b/lib/pfcp/context.h @@ -173,7 +173,7 @@ typedef struct ogs_pfcp_pdr_s { ogs_pfcp_qer_t *qer; int num_of_flow; - char *flow_description[OGS_MAX_NUM_OF_FLOW]; + char *flow_description[OGS_MAX_NUM_OF_FLOW_IN_PDR]; ogs_list_t rule_list; /* Rule List */ diff --git a/lib/pfcp/handler.c b/lib/pfcp/handler.c index 9cccaffd3..258fa2c97 100644 --- a/lib/pfcp/handler.c +++ b/lib/pfcp/handler.c @@ -313,7 +313,7 @@ ogs_pfcp_pdr_t *ogs_pfcp_handle_create_pdr(ogs_pfcp_sess_t *sess, ogs_pfcp_rule_remove_all(pdr); - for (i = 0; i < OGS_MAX_NUM_OF_FLOW; i++) { + for (i = 0; i < OGS_MAX_NUM_OF_FLOW_IN_PDR; i++) { ogs_pfcp_sdf_filter_t sdf_filter; ogs_pfcp_rule_t *rule = NULL; ogs_pfcp_rule_t *oppsite_direction_rule = NULL; @@ -558,7 +558,7 @@ ogs_pfcp_pdr_t *ogs_pfcp_handle_update_pdr(ogs_pfcp_sess_t *sess, ogs_pfcp_rule_remove_all(pdr); - for (i = 0; i < OGS_MAX_NUM_OF_FLOW; i++) { + for (i = 0; i < OGS_MAX_NUM_OF_FLOW_IN_PDR; i++) { ogs_pfcp_sdf_filter_t sdf_filter; ogs_pfcp_rule_t *rule = NULL; ogs_pfcp_rule_t *oppsite_direction_rule = NULL; diff --git a/src/pcf/npcf-handler.c b/src/pcf/npcf-handler.c index 4ab3ad15d..fcacaf1e6 100644 --- a/src/pcf/npcf-handler.c +++ b/src/pcf/npcf-handler.c @@ -455,7 +455,11 @@ bool pcf_npcf_policyauthorization_handle_create(pcf_sess_t *sess, fDescList = SubComponent->f_descs; OpenAPI_list_for_each(fDescList, node3) { - ogs_flow_t *flow = &sub->flow[sub->num_of_flow]; + ogs_flow_t *flow = NULL; + + ogs_assert(sub->num_of_flow < + OGS_MAX_NUM_OF_FLOW_IN_MEDIA_SUB_COMPONENT); + flow = &sub->flow[sub->num_of_flow]; if (node3->data) { flow->description = ogs_strdup(node3->data); ogs_assert(flow->description); diff --git a/src/pcrf/pcrf-gx-path.c b/src/pcrf/pcrf-gx-path.c index 4c041dd63..a7de68218 100644 --- a/src/pcrf/pcrf-gx-path.c +++ b/src/pcrf/pcrf-gx-path.c @@ -1435,7 +1435,8 @@ static int matched_flow(ogs_pcc_rule_t *pcc_rule, continue; } - for (j = 0; j < sub->num_of_flow; j++) { + for (j = 0; j < sub->num_of_flow && + j < OGS_MAX_NUM_OF_FLOW_IN_MEDIA_SUB_COMPONENT; j++) { ogs_flow_t gx_flow; ogs_flow_t *rx_flow = &sub->flow[j]; @@ -1484,11 +1485,12 @@ static int install_flow(ogs_pcc_rule_t *pcc_rule, } /* Copy Flow to PCC Rule */ - for (j = 0; j < sub->num_of_flow; j++) { + for (j = 0; j < sub->num_of_flow && + j < OGS_MAX_NUM_OF_FLOW_IN_MEDIA_SUB_COMPONENT; j++) { ogs_flow_t *rx_flow = NULL; ogs_flow_t *gx_flow = NULL; - if (pcc_rule->num_of_flow < OGS_MAX_NUM_OF_FLOW) { + if (pcc_rule->num_of_flow < OGS_MAX_NUM_OF_FLOW_IN_PCC_RULE) { rx_flow = &sub->flow[j]; gx_flow = &pcc_rule->flow[pcc_rule->num_of_flow]; @@ -1530,7 +1532,8 @@ static int update_qos(ogs_pcc_rule_t *pcc_rule, continue; } - for (j = 0; j < sub->num_of_flow; j++) { + for (j = 0; j < sub->num_of_flow && + j < OGS_MAX_NUM_OF_FLOW_IN_MEDIA_SUB_COMPONENT; j++) { ogs_flow_t gx_flow; ogs_flow_t *rx_flow = &sub->flow[j]; diff --git a/src/pcrf/pcrf-rx-path.c b/src/pcrf/pcrf-rx-path.c index d93dafa11..89eaae983 100644 --- a/src/pcrf/pcrf-rx-path.c +++ b/src/pcrf/pcrf-rx-path.c @@ -281,6 +281,8 @@ static int pcrf_rx_aar_cb( struct msg **msg, struct avp *avp, hdr->avp_value->i32; break; case OGS_DIAM_RX_AVP_CODE_FLOW_DESCRIPTION: + ogs_assert(sub->num_of_flow < + OGS_MAX_NUM_OF_FLOW_IN_MEDIA_SUB_COMPONENT); flow = &sub->flow[sub->num_of_flow]; /* IE (IPV4-local-addr field ) is not supported on diff --git a/src/smf/binding.c b/src/smf/binding.c index c0650e9ac..db3a540c0 100644 --- a/src/smf/binding.c +++ b/src/smf/binding.c @@ -87,6 +87,7 @@ static void encode_traffic_flow_template( if (tft_operation_code != OGS_GTP_TFT_CODE_DELETE_EXISTING_TFT && tft_operation_code != OGS_GTP_TFT_CODE_NO_TFT_OPERATION) { ogs_list_for_each_entry(&bearer->pf_to_add_list, pf, to_add_node) { + ogs_assert(i < OGS_MAX_NUM_OF_FLOW_IN_GTP); tft->pf[i].identifier = pf->identifier - 1; /* Deletion of packet filters @@ -270,6 +271,10 @@ void smf_bearer_binding(smf_sess_t *sess) } pf = smf_pf_add(bearer); + if (!pf) { + ogs_error("Overflow: PacketFilter in Bearer"); + break; + } ogs_assert(pf); pf->direction = flow->direction; @@ -336,10 +341,15 @@ void smf_bearer_binding(smf_sess_t *sess) ogs_gtp_tft_t tft; memset(&tft, 0, sizeof tft); - if (pcc_rule->num_of_flow) + if (pcc_rule->num_of_flow) { + if (ogs_list_count(&bearer->pf_to_add_list) == 0) { + ogs_error("No need to send 'Update Bearer Request'"); + continue; + } encode_traffic_flow_template( &tft, bearer, OGS_GTP_TFT_CODE_ADD_PACKET_FILTERS_TO_EXISTING_TFT); + } memset(&h, 0, sizeof(ogs_gtp_header_t)); h.type = OGS_GTP_UPDATE_BEARER_REQUEST_TYPE; diff --git a/src/smf/context.c b/src/smf/context.c index 0ca5709f1..e7ab1f7a1 100644 --- a/src/smf/context.c +++ b/src/smf/context.c @@ -59,7 +59,8 @@ void smf_context_init(void) ogs_pool_init(&smf_sess_pool, ogs_app()->pool.sess); ogs_pool_init(&smf_bearer_pool, ogs_app()->pool.bearer); - ogs_pool_init(&smf_pf_pool, ogs_app()->pool.bearer * OGS_MAX_NUM_OF_FLOW); + ogs_pool_init(&smf_pf_pool, + ogs_app()->pool.bearer * OGS_MAX_NUM_OF_FLOW_IN_BEARER); self.supi_hash = ogs_hash_make(); ogs_assert(self.supi_hash); @@ -2140,17 +2141,27 @@ smf_pf_t *smf_pf_add(smf_bearer_t *bearer) memset(pf, 0, sizeof *pf); ogs_pool_alloc(&bearer->pf_identifier_pool, &pf->identifier_node); - ogs_assert(pf->identifier_node); + if (!pf->identifier_node) { + ogs_error("smf_pf_add: Expectation `pf->identifier_node' failed"); + ogs_pool_free(&smf_pf_pool, pf); + return NULL; + } pf->identifier = *(pf->identifier_node); - ogs_assert(pf->identifier > 0 && pf->identifier <= OGS_MAX_NUM_OF_FLOW); + ogs_assert(pf->identifier > 0 && pf->identifier <= + OGS_MAX_NUM_OF_FLOW_IN_BEARER); ogs_pool_alloc(&sess->pf_precedence_pool, &pf->precedence_node); - ogs_assert(pf->precedence_node); + if (!pf->precedence_node) { + ogs_error("smf_pf_add: Expectation `pf->precedence_node' failed"); + ogs_pool_free(&bearer->pf_identifier_pool, pf->identifier_node); + ogs_pool_free(&smf_pf_pool, pf); + return NULL; + } pf->precedence = *(pf->precedence_node); ogs_assert(pf->precedence > 0 && pf->precedence <= - (OGS_MAX_NUM_OF_BEARER * OGS_MAX_NUM_OF_FLOW)); + (OGS_MAX_NUM_OF_BEARER * OGS_MAX_NUM_OF_FLOW_IN_BEARER)); pf->bearer = bearer; @@ -2427,9 +2438,9 @@ void smf_pf_identifier_pool_init(smf_bearer_t *bearer) ogs_assert(bearer); - ogs_index_init(&bearer->pf_identifier_pool, OGS_MAX_NUM_OF_FLOW); + ogs_index_init(&bearer->pf_identifier_pool, OGS_MAX_NUM_OF_FLOW_IN_BEARER); - for (i = 1; i <= OGS_MAX_NUM_OF_FLOW; i++) { + for (i = 1; i <= OGS_MAX_NUM_OF_FLOW_IN_BEARER; i++) { bearer->pf_identifier_pool.array[i-1] = i; } } @@ -2448,9 +2459,10 @@ void smf_pf_precedence_pool_init(smf_sess_t *sess) ogs_assert(sess); ogs_index_init(&sess->pf_precedence_pool, - OGS_MAX_NUM_OF_BEARER * OGS_MAX_NUM_OF_FLOW); + OGS_MAX_NUM_OF_BEARER * OGS_MAX_NUM_OF_FLOW_IN_BEARER); - for (i = 1; i <= OGS_MAX_NUM_OF_BEARER * OGS_MAX_NUM_OF_FLOW; i++) { + for (i = 1; i <= + OGS_MAX_NUM_OF_BEARER * OGS_MAX_NUM_OF_FLOW_IN_BEARER; i++) { sess->pf_precedence_pool.array[i-1] = i; } } diff --git a/src/smf/gsm-build.c b/src/smf/gsm-build.c index 0fcbff271..c370ba359 100644 --- a/src/smf/gsm-build.c +++ b/src/smf/gsm-build.c @@ -265,6 +265,7 @@ static void encode_qos_rule_packet_filter( i = 0; ogs_list_for_each(&qos_flow->pf_list, pf) { + ogs_assert(i < OGS_MAX_NUM_OF_FLOW_IN_NAS); qos_rule->pf[i].direction = pf->direction; qos_rule->pf[i].identifier = pf->identifier; diff --git a/src/smf/gx-path.c b/src/smf/gx-path.c index 07c29b484..338ad45ce 100644 --- a/src/smf/gx-path.c +++ b/src/smf/gx-path.c @@ -626,7 +626,6 @@ static void smf_gx_cca_cb(void *data, struct msg **msg) smf_event_t *e = NULL; ogs_gtp_xact_t *xact = NULL; smf_sess_t *sess = NULL; - ogs_pcc_rule_t *pcc_rule = NULL; ogs_pkbuf_t *gxbuf = NULL; ogs_diam_gx_message_t *gx_message = NULL; uint16_t gxbuf_len = 0; @@ -881,6 +880,10 @@ static void smf_gx_cca_cb(void *data, struct msg **msg) case OGS_DIAM_GX_AVP_CODE_CHARGING_RULE_DEFINITION: if (gx_message->session_data.num_of_pcc_rule < OGS_MAX_NUM_OF_PCC_RULE) { + ogs_pcc_rule_t *pcc_rule = NULL; + smf_bearer_t *bearer = NULL; + int num_of_flow = 0; + pcc_rule = &gx_message->session_data.pcc_rule [gx_message->session_data.num_of_pcc_rule]; @@ -888,8 +891,21 @@ static void smf_gx_cca_cb(void *data, struct msg **msg) pcc_rule, avpch1, &error); ogs_assert(rv == OGS_OK); - pcc_rule->type = OGS_PCC_RULE_TYPE_INSTALL; - gx_message->session_data.num_of_pcc_rule++; + num_of_flow = pcc_rule->num_of_flow; + + bearer = smf_bearer_find_by_pcc_rule_name( + sess, pcc_rule->name); + if (bearer) + num_of_flow += ogs_list_count(&bearer->pf_list); + + if (num_of_flow < OGS_MAX_NUM_OF_FLOW_IN_BEARER) { + pcc_rule->type = OGS_PCC_RULE_TYPE_INSTALL; + gx_message->session_data.num_of_pcc_rule++; + } else { + ogs_error("Overflow : Num Of Flow %d", num_of_flow); + OGS_PCC_RULE_FREE(pcc_rule); + error++; + } } else { ogs_error("Overflow: Number of PCCRule"); error++; @@ -1015,7 +1031,6 @@ static int smf_gx_rar_cb( struct msg **msg, struct avp *avp, ogs_pkbuf_t *gxbuf = NULL; smf_sess_t *sess = NULL; ogs_diam_gx_message_t *gx_message = NULL; - ogs_pcc_rule_t *pcc_rule = NULL; uint32_t result_code = OGS_DIAM_UNKNOWN_SESSION_ID; int error = 0; @@ -1080,6 +1095,10 @@ static int smf_gx_rar_cb( struct msg **msg, struct avp *avp, case OGS_DIAM_GX_AVP_CODE_CHARGING_RULE_DEFINITION: if (gx_message->session_data.num_of_pcc_rule < OGS_MAX_NUM_OF_PCC_RULE) { + ogs_pcc_rule_t *pcc_rule = NULL; + smf_bearer_t *bearer = NULL; + int num_of_flow = 0; + pcc_rule = &gx_message->session_data.pcc_rule [gx_message->session_data.num_of_pcc_rule]; @@ -1089,12 +1108,27 @@ static int smf_gx_rar_cb( struct msg **msg, struct avp *avp, if (error) { ogs_error("decode_pcc_rule_definition() failed"); + OGS_PCC_RULE_FREE(pcc_rule); result_code = OGS_DIAM_GX_DIAMETER_PCC_RULE_EVENT; goto out; } - pcc_rule->type = OGS_PCC_RULE_TYPE_INSTALL; - gx_message->session_data.num_of_pcc_rule++; + num_of_flow = pcc_rule->num_of_flow; + + bearer = smf_bearer_find_by_pcc_rule_name( + sess, pcc_rule->name); + if (bearer) + num_of_flow += ogs_list_count(&bearer->pf_list); + + if (num_of_flow < OGS_MAX_NUM_OF_FLOW_IN_BEARER) { + pcc_rule->type = OGS_PCC_RULE_TYPE_INSTALL; + gx_message->session_data.num_of_pcc_rule++; + } else { + ogs_error("Overflow : Num Of Flow %d", num_of_flow); + OGS_PCC_RULE_FREE(pcc_rule); + result_code = OGS_DIAM_GX_DIAMETER_PCC_RULE_EVENT; + goto out; + } } else { ogs_error("Overflow: Number of PCCRule"); } @@ -1116,7 +1150,8 @@ static int smf_gx_rar_cb( struct msg **msg, struct avp *avp, case OGS_DIAM_GX_AVP_CODE_CHARGING_RULE_NAME: if (gx_message->session_data.num_of_pcc_rule < OGS_MAX_NUM_OF_PCC_RULE) { - pcc_rule = &gx_message->session_data.pcc_rule + ogs_pcc_rule_t *pcc_rule = + &gx_message->session_data.pcc_rule [gx_message->session_data.num_of_pcc_rule]; pcc_rule->name = ogs_strdup( @@ -1291,7 +1326,7 @@ static int decode_pcc_rule_definition( ogs_assert(pcc_rule->name); break; case OGS_DIAM_GX_AVP_CODE_FLOW_INFORMATION: - if (pcc_rule->num_of_flow < OGS_MAX_NUM_OF_FLOW) { + if (pcc_rule->num_of_flow < OGS_MAX_NUM_OF_FLOW_IN_PCC_RULE) { flow = &pcc_rule->flow[pcc_rule->num_of_flow]; ret = fd_avp_search_avp( diff --git a/src/smf/s5c-handler.c b/src/smf/s5c-handler.c index f3db22f7f..3613f5993 100644 --- a/src/smf/s5c-handler.c +++ b/src/smf/s5c-handler.c @@ -999,7 +999,8 @@ void smf_s5c_handle_bearer_resource_command( tft_delete = 1; } else if (tft.code == OGS_GTP_TFT_CODE_REPLACE_PACKET_FILTERS_IN_EXISTING) { - for (i = 0; i < tft.num_of_packet_filter; i++) { + for (i = 0; i < tft.num_of_packet_filter && + i < OGS_MAX_NUM_OF_FLOW_IN_GTP; i++) { pf = smf_pf_find_by_id(bearer, tft.pf[i].identifier+1); if (pf) { if (reconfigure_packet_filter(pf, &tft, i) < 0) { @@ -1064,7 +1065,8 @@ void smf_s5c_handle_bearer_resource_command( if (tft.code == OGS_GTP_TFT_CODE_CREATE_NEW_TFT) smf_pf_remove_all(bearer); - for (i = 0; i < tft.num_of_packet_filter; i++) { + for (i = 0; i < tft.num_of_packet_filter && + i < OGS_MAX_NUM_OF_FLOW_IN_GTP; i++) { pf = smf_pf_find_by_id(bearer, tft.pf[i].identifier+1); if (!pf) pf = smf_pf_add(bearer); @@ -1128,7 +1130,8 @@ void smf_s5c_handle_bearer_resource_command( } } else if (tft.code == OGS_GTP_TFT_CODE_DELETE_PACKET_FILTERS_FROM_EXISTING) { - for (i = 0; i < tft.num_of_packet_filter; i++) { + for (i = 0; i < tft.num_of_packet_filter && + i <= OGS_MAX_NUM_OF_FLOW_IN_GTP; i++) { pf = smf_pf_find_by_id(bearer, tft.pf[i].identifier+1); if (pf) smf_pf_remove(pf);