diff --git a/lib/diameter/s6b/message.h b/lib/diameter/s6b/message.h index 25e19e26df..1431951096 100644 --- a/lib/diameter/s6b/message.h +++ b/lib/diameter/s6b/message.h @@ -1,4 +1,4 @@ -/* +/* 3GPP TS 29.273 section 9 * Copyright (C) 2019 by Sukchan Lee * * This file is part of Open5GS. @@ -35,7 +35,8 @@ extern struct dict_object *ogs_diam_s6b_application; extern struct dict_object *ogs_diam_s6b_mip6_feature_vector; typedef struct ogs_diam_s6b_message_s { -#define OGS_DIAM_S6B_CMD_SESSION_TERMINATION 1 +#define OGS_DIAM_S6B_CMD_AUTHENTICATION_AUTHORIZATION 1 +#define OGS_DIAM_S6B_CMD_SESSION_TERMINATION 2 uint16_t cmd_code; uint32_t result_code; uint32_t *err; diff --git a/src/smf/context.h b/src/smf/context.h index a9f2b73118..94055b60d7 100644 --- a/src/smf/context.h +++ b/src/smf/context.h @@ -228,6 +228,8 @@ typedef struct smf_sess_s { uint32_t gx_cca_init_err; /* Gx CCA RXed error code */ bool gy_ccr_init_in_flight; /* Waiting for Gy CCA */ uint32_t gy_cca_init_err; /* Gy CCA RXed error code */ + bool s6b_aar_in_flight; /* Waiting for S6B AAR */ + uint32_t s6b_aaa_err; /* S6B AAA RXed error code */ bool gx_ccr_term_in_flight; /* Waiting for Gx CCA */ uint32_t gx_cca_term_err; /* Gx CCA RXed error code */ bool gy_ccr_term_in_flight; /* Waiting for Gy CCA */ diff --git a/src/smf/gsm-sm.c b/src/smf/gsm-sm.c index be10244b94..d49600d990 100644 --- a/src/smf/gsm-sm.c +++ b/src/smf/gsm-sm.c @@ -229,7 +229,9 @@ void smf_gsm_state_initial(ogs_fsm_t *s, smf_event_t *e) break; case OGS_GTP2_RAT_TYPE_WLAN: smf_s6b_send_aar(sess, e->gtp_xact); + sess->sm_data.s6b_aar_in_flight = true; OGS_FSM_TRAN(s, smf_gsm_state_wait_epc_auth_initial); + /* Gx/Gy Init Req is done after s6b AAR + AAA */ break; default: ogs_error("Unknown RAT Type [%d]", sess->gtp_rat_type); @@ -327,6 +329,7 @@ void smf_gsm_state_wait_epc_auth_initial(ogs_fsm_t *s, smf_event_t *e) { smf_sess_t *sess = NULL; + ogs_diam_s6b_message_t *s6b_message = NULL; ogs_diam_gy_message_t *gy_message = NULL; ogs_diam_gx_message_t *gx_message = NULL; uint32_t diam_err; @@ -340,6 +343,22 @@ void smf_gsm_state_wait_epc_auth_initial(ogs_fsm_t *s, smf_event_t *e) ogs_assert(sess); switch (e->h.id) { + case SMF_EVT_S6B_MESSAGE: + s6b_message = e->s6b_message; + ogs_assert(s6b_message); + + switch(s6b_message->cmd_code) { + case OGS_DIAM_S6B_CMD_AUTHENTICATION_AUTHORIZATION: + sess->sm_data.s6b_aar_in_flight = false; + sess->sm_data.s6b_aaa_err = s6b_message->result_code; + if (s6b_message->result_code == ER_DIAMETER_SUCCESS) { + send_ccr_init_req_gx_gy(sess, e); + return; + } + goto test_can_proceed; + } + break; + case SMF_EVT_GX_MESSAGE: gx_message = e->gx_message; ogs_assert(gx_message); @@ -382,9 +401,12 @@ void smf_gsm_state_wait_epc_auth_initial(ogs_fsm_t *s, smf_event_t *e) test_can_proceed: /* First wait for both Gx and Gy requests to be done: */ - if (!sess->sm_data.gx_ccr_init_in_flight && + if (!sess->sm_data.s6b_aar_in_flight && + !sess->sm_data.gx_ccr_init_in_flight && !sess->sm_data.gy_ccr_init_in_flight) { diam_err = ER_DIAMETER_SUCCESS; + if (sess->sm_data.s6b_aaa_err != ER_DIAMETER_SUCCESS) + diam_err = sess->sm_data.s6b_aaa_err; if (sess->sm_data.gx_cca_init_err != ER_DIAMETER_SUCCESS) diam_err = sess->sm_data.gx_cca_init_err; if (sess->sm_data.gy_cca_init_err != ER_DIAMETER_SUCCESS) diff --git a/src/smf/s6b-path.c b/src/smf/s6b-path.c index 0dff339010..09f080cd09 100644 --- a/src/smf/s6b-path.c +++ b/src/smf/s6b-path.c @@ -1,4 +1,4 @@ -/* +/* 3GPP TS 29.273 section 9 * Copyright (C) 2019 by Sukchan Lee * * This file is part of Open5GS. @@ -344,11 +344,11 @@ static void smf_s6b_aaa_cb(void *data, struct msg **msg) unsigned long dur; int error = 0; int new; - int result_code = 0; - int exp_result_code = 0; smf_sess_t *sess = NULL; ogs_gtp_xact_t *xact = NULL; + smf_event_t *e = NULL; + ogs_diam_s6b_message_t *s6b_message = NULL; ogs_debug("[AA-Answer]"); @@ -374,15 +374,20 @@ static void smf_s6b_aaa_cb(void *data, struct msg **msg) xact = sess_data->xact; ogs_assert(xact); + s6b_message = ogs_calloc(1, sizeof(ogs_diam_s6b_message_t)); + ogs_assert(s6b_message); + /* Set Session Termination Command */ + s6b_message->cmd_code = OGS_DIAM_S6B_CMD_AUTHENTICATION_AUTHORIZATION; + /* Value of Result Code */ ret = fd_msg_search_avp(*msg, ogs_diam_result_code, &avp); ogs_assert(ret == 0); if (avp) { ret = fd_msg_avp_hdr(avp, &hdr); ogs_assert(ret == 0); - result_code = hdr->avp_value->i32; - if (result_code != ER_DIAMETER_SUCCESS) { - ogs_error("Result Code: %d", result_code); + s6b_message->result_code = hdr->avp_value->i32; + if (s6b_message->result_code != ER_DIAMETER_SUCCESS) { + ogs_error("Result Code: %d", s6b_message->result_code); error++; } } else { @@ -397,8 +402,8 @@ static void smf_s6b_aaa_cb(void *data, struct msg **msg) if (avpch1) { ret = fd_msg_avp_hdr(avpch1, &hdr); ogs_assert(ret == 0); - exp_result_code = hdr->avp_value->i32; - ogs_error("Experimental Result Code: %d", exp_result_code); + s6b_message->result_code = hdr->avp_value->i32; + ogs_error("Experimental Result Code: %d", s6b_message->result_code); } } else { ogs_error("no Result-Code"); @@ -431,9 +436,22 @@ static void smf_s6b_aaa_cb(void *data, struct msg **msg) error++; } - if (!error) { - smf_gx_send_ccr(sess, xact, - OGS_DIAM_GX_CC_REQUEST_TYPE_INITIAL_REQUEST); + e = smf_event_new(SMF_EVT_S6B_MESSAGE); + ogs_assert(e); + + if (error && s6b_message->result_code == ER_DIAMETER_SUCCESS) + s6b_message->result_code = error; + + e->sess = sess; + e->gtp_xact = xact; + e->s6b_message = s6b_message; + ret = ogs_queue_push(ogs_app()->queue, e); + if (ret != OGS_OK) { + ogs_error("ogs_queue_push() failed:%d", (int)ret); + ogs_free(s6b_message); + ogs_event_free(e); + } else { + ogs_pollset_notify(ogs_app()->pollset); } /* Free the message */ diff --git a/src/smf/smf-sm.c b/src/smf/smf-sm.c index c0369fbea4..7c841dda00 100644 --- a/src/smf/smf-sm.c +++ b/src/smf/smf-sm.c @@ -365,6 +365,7 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) ogs_assert(sess); switch(s6b_message->cmd_code) { + case OGS_DIAM_S6B_CMD_AUTHENTICATION_AUTHORIZATION: case OGS_DIAM_S6B_CMD_SESSION_TERMINATION: ogs_fsm_dispatch(&sess->sm, e); break;