forked from acouzens/open5gs
[SMF] Gx: Fix crash receiving DIAMETER_UNABLE_TO_DELIVER (#1469)
This commit is contained in:
parent
5be48be634
commit
8286b1c417
|
@ -23,6 +23,24 @@
|
||||||
#include "gx-handler.h"
|
#include "gx-handler.h"
|
||||||
#include "binding.h"
|
#include "binding.h"
|
||||||
|
|
||||||
|
static uint8_t gtp_cause_from_diameter(
|
||||||
|
const uint32_t *dia_err, const uint32_t *dia_exp_err)
|
||||||
|
{
|
||||||
|
if (dia_exp_err) {
|
||||||
|
}
|
||||||
|
if (dia_err) {
|
||||||
|
switch (*dia_err) {
|
||||||
|
case OGS_DIAM_UNKNOWN_SESSION_ID:
|
||||||
|
return OGS_GTP_CAUSE_APN_ACCESS_DENIED_NO_SUBSCRIPTION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ogs_error("Unexpected Diameter Result Code %d/%d, defaulting to severe "
|
||||||
|
"network failure",
|
||||||
|
dia_err ? *dia_err : -1, dia_exp_err ? *dia_exp_err : -1);
|
||||||
|
return OGS_GTP_CAUSE_UE_NOT_AUTHORISED_BY_OCS_OR_EXTERNAL_AAA_SERVER;
|
||||||
|
}
|
||||||
|
|
||||||
void smf_gx_handle_cca_initial_request(
|
void smf_gx_handle_cca_initial_request(
|
||||||
smf_sess_t *sess, ogs_diam_gx_message_t *gx_message,
|
smf_sess_t *sess, ogs_diam_gx_message_t *gx_message,
|
||||||
ogs_gtp_xact_t *gtp_xact)
|
ogs_gtp_xact_t *gtp_xact)
|
||||||
|
@ -48,6 +66,19 @@ void smf_gx_handle_cca_initial_request(
|
||||||
ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]",
|
ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]",
|
||||||
sess->sgw_s5c_teid, sess->smf_n4_teid);
|
sess->sgw_s5c_teid, sess->smf_n4_teid);
|
||||||
|
|
||||||
|
if (gx_message->result_code != ER_DIAMETER_SUCCESS) {
|
||||||
|
uint8_t cause_value = gtp_cause_from_diameter(
|
||||||
|
gx_message->err, gx_message->exp_err);
|
||||||
|
|
||||||
|
if (gtp_xact->gtp_version == 1)
|
||||||
|
ogs_gtp1_send_error_message(gtp_xact, sess ? sess->sgw_s5c_teid : 0,
|
||||||
|
OGS_GTP1_CREATE_PDP_CONTEXT_RESPONSE_TYPE, cause_value);
|
||||||
|
else
|
||||||
|
ogs_gtp_send_error_message(gtp_xact, sess ? sess->sgw_s5c_teid : 0,
|
||||||
|
OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, cause_value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
sess->policy.num_of_pcc_rule = gx_message->session_data.num_of_pcc_rule;
|
sess->policy.num_of_pcc_rule = gx_message->session_data.num_of_pcc_rule;
|
||||||
for (i = 0; i < gx_message->session_data.num_of_pcc_rule; i++)
|
for (i = 0; i < gx_message->session_data.num_of_pcc_rule; i++)
|
||||||
OGS_STORE_PCC_RULE(&sess->policy.pcc_rule[i],
|
OGS_STORE_PCC_RULE(&sess->policy.pcc_rule[i],
|
||||||
|
|
|
@ -30,7 +30,7 @@ struct sess_state {
|
||||||
|
|
||||||
#define MAX_CC_REQUEST_NUMBER 32
|
#define MAX_CC_REQUEST_NUMBER 32
|
||||||
smf_sess_t *sess;
|
smf_sess_t *sess;
|
||||||
ogs_gtp_xact_t *xact;
|
ogs_gtp_xact_t *xact[MAX_CC_REQUEST_NUMBER];
|
||||||
|
|
||||||
uint32_t cc_request_type;
|
uint32_t cc_request_type;
|
||||||
uint32_t cc_request_number;
|
uint32_t cc_request_number;
|
||||||
|
@ -185,7 +185,7 @@ void smf_gx_send_ccr(smf_sess_t *sess, ogs_gtp_xact_t *xact,
|
||||||
|
|
||||||
/* Update session state */
|
/* Update session state */
|
||||||
sess_data->sess = sess;
|
sess_data->sess = sess;
|
||||||
sess_data->xact = xact;
|
sess_data->xact[sess_data->cc_request_number] = xact;
|
||||||
|
|
||||||
/* Set Origin-Host & Origin-Realm */
|
/* Set Origin-Host & Origin-Realm */
|
||||||
ret = fd_msg_add_origin(req, 0);
|
ret = fd_msg_add_origin(req, 0);
|
||||||
|
@ -691,7 +691,7 @@ static void smf_gx_cca_cb(void *data, struct msg **msg)
|
||||||
unsigned long dur;
|
unsigned long dur;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
int new;
|
int new;
|
||||||
|
struct msg *req = NULL;
|
||||||
smf_event_t *e = NULL;
|
smf_event_t *e = NULL;
|
||||||
ogs_gtp_xact_t *xact = NULL;
|
ogs_gtp_xact_t *xact = NULL;
|
||||||
smf_sess_t *sess = NULL;
|
smf_sess_t *sess = NULL;
|
||||||
|
@ -703,6 +703,10 @@ static void smf_gx_cca_cb(void *data, struct msg **msg)
|
||||||
ret = clock_gettime(CLOCK_REALTIME, &ts);
|
ret = clock_gettime(CLOCK_REALTIME, &ts);
|
||||||
ogs_assert(ret == 0);
|
ogs_assert(ret == 0);
|
||||||
|
|
||||||
|
/* Get originating request of received message, if any */
|
||||||
|
ret = fd_msg_answ_getq(*msg, &req);
|
||||||
|
ogs_assert(ret == 0);
|
||||||
|
|
||||||
/* Search the session, retrieve its data */
|
/* Search the session, retrieve its data */
|
||||||
ret = fd_msg_sess_get(fd_g_config->cnf_dict, *msg, &session, &new);
|
ret = fd_msg_sess_get(fd_g_config->cnf_dict, *msg, &session, &new);
|
||||||
ogs_assert(ret == 0);
|
ogs_assert(ret == 0);
|
||||||
|
@ -717,7 +721,27 @@ static void smf_gx_cca_cb(void *data, struct msg **msg)
|
||||||
|
|
||||||
ogs_debug(" Retrieve its data: [%s]", sess_data->gx_sid);
|
ogs_debug(" Retrieve its data: [%s]", sess_data->gx_sid);
|
||||||
|
|
||||||
xact = sess_data->xact;
|
/* Value of CC-Request-Number */
|
||||||
|
ret = fd_msg_search_avp(*msg, ogs_diam_gx_cc_request_number, &avp);
|
||||||
|
ogs_assert(ret == 0);
|
||||||
|
if (!avp && req) {
|
||||||
|
/* Attempt searching for CC-Request-* in original request. Error
|
||||||
|
* messages (like DIAMETER_UNABLE_TO_DELIVER) crafted internally may not
|
||||||
|
* have them. */
|
||||||
|
ret = fd_msg_search_avp(req, ogs_diam_gx_cc_request_number, &avp);
|
||||||
|
ogs_assert(ret == 0);
|
||||||
|
}
|
||||||
|
if (!avp) {
|
||||||
|
ogs_error("no_CC-Request-Number");
|
||||||
|
ogs_assert_if_reached();
|
||||||
|
}
|
||||||
|
ret = fd_msg_avp_hdr(avp, &hdr);
|
||||||
|
ogs_assert(ret == 0);
|
||||||
|
cc_request_number = hdr->avp_value->i32;
|
||||||
|
|
||||||
|
ogs_debug(" CC-Request-Number[%d]", cc_request_number);
|
||||||
|
|
||||||
|
xact = sess_data->xact[cc_request_number];
|
||||||
ogs_assert(xact);
|
ogs_assert(xact);
|
||||||
sess = sess_data->sess;
|
sess = sess_data->sess;
|
||||||
ogs_assert(sess);
|
ogs_assert(sess);
|
||||||
|
@ -784,37 +808,29 @@ static void smf_gx_cca_cb(void *data, struct msg **msg)
|
||||||
error++;
|
error++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Value of CC-Request-Type */
|
||||||
|
ret = fd_msg_search_avp(*msg, ogs_diam_gx_cc_request_type, &avp);
|
||||||
|
ogs_assert(ret == 0);
|
||||||
|
if (!avp && req) {
|
||||||
|
/* Attempt searching for CC-Request-* in original request. Error
|
||||||
|
* messages (like DIAMETER_UNABLE_TO_DELIVER) crafted internally may not
|
||||||
|
* have them. */
|
||||||
|
ret = fd_msg_search_avp(req, ogs_diam_gx_cc_request_type, &avp);
|
||||||
|
ogs_assert(ret == 0);
|
||||||
|
}
|
||||||
|
if (!avp) {
|
||||||
|
ogs_error("no_CC-Request-Number");
|
||||||
|
error++;
|
||||||
|
}
|
||||||
|
ret = fd_msg_avp_hdr(avp, &hdr);
|
||||||
|
ogs_assert(ret == 0);
|
||||||
|
gx_message->cc_request_type = hdr->avp_value->i32;
|
||||||
|
|
||||||
if (gx_message->result_code != ER_DIAMETER_SUCCESS) {
|
if (gx_message->result_code != ER_DIAMETER_SUCCESS) {
|
||||||
ogs_warn("ERROR DIAMETER Result Code(%d)", gx_message->result_code);
|
ogs_warn("ERROR DIAMETER Result Code(%d)", gx_message->result_code);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Value of CC-Request-Type */
|
|
||||||
ret = fd_msg_search_avp(*msg, ogs_diam_gx_cc_request_type, &avp);
|
|
||||||
ogs_assert(ret == 0);
|
|
||||||
if (avp) {
|
|
||||||
ret = fd_msg_avp_hdr(avp, &hdr);
|
|
||||||
ogs_assert(ret == 0);
|
|
||||||
gx_message->cc_request_type = hdr->avp_value->i32;
|
|
||||||
} else {
|
|
||||||
ogs_error("no_CC-Request-Type");
|
|
||||||
error++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Value of CC-Request-Number */
|
|
||||||
ret = fd_msg_search_avp(*msg, ogs_diam_gx_cc_request_number, &avp);
|
|
||||||
ogs_assert(ret == 0);
|
|
||||||
if (avp) {
|
|
||||||
ret = fd_msg_avp_hdr(avp, &hdr);
|
|
||||||
ogs_assert(ret == 0);
|
|
||||||
cc_request_number = hdr->avp_value->i32;
|
|
||||||
} else {
|
|
||||||
ogs_error("no_CC-Request-Number");
|
|
||||||
error++;
|
|
||||||
}
|
|
||||||
|
|
||||||
ogs_debug(" CC-Request-Number[%d]", cc_request_number);
|
|
||||||
|
|
||||||
ret = fd_msg_search_avp(*msg, ogs_diam_gx_qos_information, &avp);
|
ret = fd_msg_search_avp(*msg, ogs_diam_gx_qos_information, &avp);
|
||||||
ogs_assert(ret == 0);
|
ogs_assert(ret == 0);
|
||||||
if (avp) {
|
if (avp) {
|
||||||
|
|
|
@ -29,26 +29,6 @@
|
||||||
#include "namf-handler.h"
|
#include "namf-handler.h"
|
||||||
#include "npcf-handler.h"
|
#include "npcf-handler.h"
|
||||||
|
|
||||||
static uint8_t gtp_cause_from_diameter(
|
|
||||||
const uint32_t *dia_err, const uint32_t *dia_exp_err)
|
|
||||||
{
|
|
||||||
if (dia_exp_err) {
|
|
||||||
}
|
|
||||||
if (dia_err) {
|
|
||||||
switch (*dia_err) {
|
|
||||||
case OGS_DIAM_UNKNOWN_SESSION_ID:
|
|
||||||
return OGS_GTP_CAUSE_APN_ACCESS_DENIED_NO_SUBSCRIPTION;
|
|
||||||
case ER_DIAMETER_UNABLE_TO_DELIVER:
|
|
||||||
return OGS_GTP_CAUSE_REMOTE_PEER_NOT_RESPONDING;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ogs_error("Unexpected Diameter Result Code %d/%d, defaulting to severe "
|
|
||||||
"network failure",
|
|
||||||
dia_err ? *dia_err : -1, dia_exp_err ? *dia_exp_err : -1);
|
|
||||||
return OGS_GTP_CAUSE_UE_NOT_AUTHORISED_BY_OCS_OR_EXTERNAL_AAA_SERVER;
|
|
||||||
}
|
|
||||||
|
|
||||||
void smf_state_initial(ogs_fsm_t *s, smf_event_t *e)
|
void smf_state_initial(ogs_fsm_t *s, smf_event_t *e)
|
||||||
{
|
{
|
||||||
smf_sm_debug(e);
|
smf_sm_debug(e);
|
||||||
|
@ -263,22 +243,6 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
|
||||||
gtp_xact = e->gtp_xact;
|
gtp_xact = e->gtp_xact;
|
||||||
ogs_assert(gtp_xact);
|
ogs_assert(gtp_xact);
|
||||||
|
|
||||||
if (gx_message->result_code != ER_DIAMETER_SUCCESS) {
|
|
||||||
uint8_t cause_value = gtp_cause_from_diameter(
|
|
||||||
gx_message->err, gx_message->exp_err);
|
|
||||||
|
|
||||||
if (gtp_xact->gtp_version == 1)
|
|
||||||
ogs_gtp1_send_error_message(
|
|
||||||
gtp_xact, sess ? sess->sgw_s5c_teid : 0,
|
|
||||||
OGS_GTP1_CREATE_PDP_CONTEXT_RESPONSE_TYPE, cause_value);
|
|
||||||
else
|
|
||||||
ogs_gtp_send_error_message(
|
|
||||||
gtp_xact, sess ? sess->sgw_s5c_teid : 0,
|
|
||||||
OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, cause_value);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(gx_message->cc_request_type) {
|
switch(gx_message->cc_request_type) {
|
||||||
case OGS_DIAM_GX_CC_REQUEST_TYPE_INITIAL_REQUEST:
|
case OGS_DIAM_GX_CC_REQUEST_TYPE_INITIAL_REQUEST:
|
||||||
smf_gx_handle_cca_initial_request(
|
smf_gx_handle_cca_initial_request(
|
||||||
|
|
Loading…
Reference in New Issue