forked from acouzens/open5gs
temporal update
This commit is contained in:
parent
682eee215b
commit
1de4e8d446
|
@ -7,7 +7,7 @@ libmme_la_SOURCES = \
|
|||
mme_event.h mme_context.h \
|
||||
s1ap_build.h s1ap_handler.h s1ap_conv.h s1ap_path.h \
|
||||
mme_fd.h mme_s6a_handler.h \
|
||||
nas_conv.h nas_security.h \
|
||||
nas_conv.h nas_security.h nas_path.h \
|
||||
emm_handler.h emm_build.h \
|
||||
esm_handler.h esm_build.h \
|
||||
mme_s11_path.h mme_s11_build.h mme_s11_handler.h \
|
||||
|
@ -18,7 +18,8 @@ nodist_libmme_la_SOURCES = \
|
|||
mme_init.c mme_event.c mme_context.c \
|
||||
s1ap_sm.c s1ap_build.c s1ap_handler.c s1ap_conv.c s1ap_path.c \
|
||||
mme_fd.c mme_s6a_handler.c \
|
||||
nas_conv.c nas_security.c emm_sm.c emm_handler.c emm_build.c \
|
||||
nas_conv.c nas_security.c nas_path.c \
|
||||
emm_sm.c emm_handler.c emm_build.c \
|
||||
esm_sm.c esm_handler.c esm_build.c \
|
||||
mme_s11_path.c mme_s11_build.c mme_s11_handler.c \
|
||||
mme_sm.c
|
||||
|
|
|
@ -10,26 +10,64 @@
|
|||
#include "mme_kdf.h"
|
||||
#include "nas_security.h"
|
||||
#include "nas_conv.h"
|
||||
#include "mme_s6a_handler.h"
|
||||
#include "esm_build.h"
|
||||
#include "emm_build.h"
|
||||
#include "s1ap_build.h"
|
||||
#include "s1ap_path.h"
|
||||
#include "fd_lib.h"
|
||||
#include "nas_path.h"
|
||||
|
||||
#include "mme_s11_build.h"
|
||||
#include "mme_s11_path.h"
|
||||
|
||||
#include "emm_handler.h"
|
||||
|
||||
static status_t emm_send_to_enb(enb_ue_t *enb_ue, pkbuf_t *pkbuf);
|
||||
static status_t emm_send_downlink_nas_transport(
|
||||
mme_ue_t *mme_ue, pkbuf_t *pkbuf);
|
||||
static status_t emm_send_initial_context_setup_request(
|
||||
mme_sess_t *sess, int with_attach_accept);
|
||||
static void emm_handle_esm_message_container(
|
||||
mme_ue_t *mme_ue, nas_esm_message_container_t *esm_message_container);
|
||||
static mme_sess_t *emm_sess_find_by_ue(mme_ue_t *mme_ue);
|
||||
static mme_sess_t *emm_sess_find_by_ue(mme_ue_t *mme_ue)
|
||||
{
|
||||
/* TODO : fix the current transaction from the PDN connectivity request's PTI */
|
||||
return mme_sess_first(mme_ue);
|
||||
}
|
||||
|
||||
static void event_emm_to_esm(
|
||||
mme_ue_t *mme_ue, nas_esm_message_container_t *esm_message_container)
|
||||
{
|
||||
pkbuf_t *esmbuf = NULL;
|
||||
event_t e;
|
||||
|
||||
nas_esm_header_t *h = NULL;
|
||||
c_uint8_t pti = NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED;
|
||||
c_uint8_t ebi = NAS_EPS_BEARER_IDENTITY_UNASSIGNED;
|
||||
mme_bearer_t *bearer = NULL;
|
||||
|
||||
d_assert(mme_ue, return, "Null param");
|
||||
d_assert(esm_message_container, return, "Null param");
|
||||
d_assert(esm_message_container->len, return, "Null param");
|
||||
|
||||
h = (nas_esm_header_t *)esm_message_container->data;
|
||||
d_assert(h, return, "Null param");
|
||||
|
||||
pti = h->procedure_transaction_identity;
|
||||
ebi = h->eps_bearer_identity;
|
||||
if (pti == NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED && ebi)
|
||||
bearer = mme_bearer_find_by_ue_ebi(mme_ue, ebi);
|
||||
else if (ebi == NAS_EPS_BEARER_IDENTITY_UNASSIGNED && pti)
|
||||
bearer = mme_bearer_find_by_ue_pti(mme_ue, pti);
|
||||
|
||||
if (!bearer)
|
||||
bearer = mme_sess_add(mme_ue, pti);
|
||||
d_assert(bearer, return, "No Bearer Context");
|
||||
|
||||
/* The Packet Buffer(pkbuf_t) for NAS message MUST make a HEADROOM.
|
||||
* When calculating AES_CMAC, we need to use the headroom of the packet. */
|
||||
esmbuf = pkbuf_alloc(NAS_HEADROOM, esm_message_container->len);
|
||||
d_assert(esmbuf, return, "Null param");
|
||||
memcpy(esmbuf->payload,
|
||||
esm_message_container->data, esm_message_container->len);
|
||||
|
||||
event_set(&e, MME_EVT_ESM_BEARER_MSG);
|
||||
event_set_param1(&e, (c_uintptr_t)bearer->index);
|
||||
event_set_param3(&e, (c_uintptr_t)esmbuf);
|
||||
mme_event_send(&e);
|
||||
}
|
||||
|
||||
void emm_handle_attach_request(
|
||||
mme_ue_t *mme_ue, nas_attach_request_t *attach_request)
|
||||
|
@ -42,9 +80,6 @@ void emm_handle_attach_request(
|
|||
enb_ue = mme_ue->enb_ue;
|
||||
d_assert(enb_ue, return, "Null param");
|
||||
|
||||
emm_handle_esm_message_container(
|
||||
mme_ue, &attach_request->esm_message_container);
|
||||
|
||||
/* Store UE specific information */
|
||||
if (attach_request->presencemask &
|
||||
NAS_ATTACH_REQUEST_LAST_VISITED_REGISTERED_TAI_PRESENT)
|
||||
|
@ -87,26 +122,6 @@ void emm_handle_attach_request(
|
|||
|
||||
d_trace(3, "[NAS] Attach request : IMSI[%s] --> EMM\n", imsi_bcd);
|
||||
|
||||
if (SECURITY_CONTEXT_IS_VALID(mme_ue))
|
||||
{
|
||||
/* Update Kenb */
|
||||
mme_kdf_enb(mme_ue->kasme, mme_ue->ul_count.i32, mme_ue->kenb);
|
||||
|
||||
/* Send ESM Information Request */
|
||||
emm_handle_esm_information_request(mme_ue);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (MME_SESSION_IS_CREATED(mme_ue))
|
||||
{
|
||||
emm_handle_s11_delete_session_request(mme_ue);
|
||||
}
|
||||
else
|
||||
{
|
||||
mme_s6a_send_air(mme_ue);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case NAS_EPS_MOBILE_IDENTITY_GUTI:
|
||||
|
@ -128,31 +143,7 @@ void emm_handle_attach_request(
|
|||
MME_UE_HAVE_IMSI(mme_ue)
|
||||
? mme_ue->imsi_bcd : "Unknown");
|
||||
|
||||
if (MME_UE_HAVE_IMSI(mme_ue))
|
||||
{
|
||||
/* Known GUTI */
|
||||
if (SECURITY_CONTEXT_IS_VALID(mme_ue))
|
||||
{
|
||||
/* Update Kenb */
|
||||
mme_kdf_enb(mme_ue->kasme, mme_ue->ul_count.i32,
|
||||
mme_ue->kenb);
|
||||
|
||||
/* Send ESM Information Request */
|
||||
emm_handle_esm_information_request(mme_ue);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (MME_SESSION_IS_CREATED(mme_ue))
|
||||
{
|
||||
emm_handle_s11_delete_session_request(mme_ue);
|
||||
}
|
||||
else
|
||||
{
|
||||
mme_s6a_send_air(mme_ue);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
if (!MME_UE_HAVE_IMSI(mme_ue))
|
||||
{
|
||||
/* Unknown GUTI */
|
||||
emm_handle_identity_request(mme_ue);
|
||||
|
@ -168,16 +159,43 @@ void emm_handle_attach_request(
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
event_emm_to_esm(mme_ue, &attach_request->esm_message_container);
|
||||
}
|
||||
|
||||
void emm_handle_attach_accept(mme_ue_t *mme_ue)
|
||||
{
|
||||
status_t rv;
|
||||
enb_ue_t *enb_ue = NULL;
|
||||
mme_sess_t *sess = NULL;
|
||||
mme_bearer_t *bearer = NULL;
|
||||
pkbuf_t *esmbuf = NULL, *emmbuf = NULL, *s1apbuf = NULL;
|
||||
|
||||
d_assert(mme_ue, return, "Null param");
|
||||
sess = emm_sess_find_by_ue(mme_ue);
|
||||
d_assert(sess, return, "Null param");
|
||||
enb_ue = mme_ue->enb_ue;
|
||||
d_assert(enb_ue, return, "Null param");
|
||||
bearer = mme_default_bearer_in_sess(sess);
|
||||
d_assert(bearer, return, "Null param");
|
||||
|
||||
d_assert(emm_send_initial_context_setup_request(sess, 1) == CORE_OK,,);
|
||||
rv = esm_build_activate_default_bearer_context(&esmbuf, bearer);
|
||||
d_assert(rv == CORE_OK && esmbuf, return, "bearer build error");
|
||||
|
||||
d_trace(3, "[NAS] Activate default bearer context request : "
|
||||
"EMM <-- ESM[%d]\n", bearer->ebi);
|
||||
|
||||
rv = emm_build_attach_accept(&emmbuf, mme_ue, esmbuf);
|
||||
d_assert(rv == CORE_OK && emmbuf,
|
||||
pkbuf_free(esmbuf); return, "emm build error");
|
||||
|
||||
d_trace(3, "[NAS] Attach accept : UE[%s] <-- EMM\n", mme_ue->imsi_bcd);
|
||||
|
||||
rv = s1ap_build_initial_context_setup_request(&s1apbuf, bearer, emmbuf);
|
||||
d_assert(rv == CORE_OK && s1apbuf,
|
||||
pkbuf_free(emmbuf); return, "s1ap build error");
|
||||
|
||||
d_assert(nas_send_to_enb(enb_ue, s1apbuf) == CORE_OK,,);
|
||||
}
|
||||
|
||||
void emm_handle_attach_complete(
|
||||
|
@ -198,8 +216,7 @@ void emm_handle_attach_complete(
|
|||
|
||||
d_assert(mme_ue, return, "Null param");
|
||||
|
||||
emm_handle_esm_message_container(
|
||||
mme_ue, &attach_complete->esm_message_container);
|
||||
event_emm_to_esm(mme_ue, &attach_complete->esm_message_container);
|
||||
|
||||
memset(&message, 0, sizeof(message));
|
||||
message.h.security_header_type =
|
||||
|
@ -237,7 +254,7 @@ void emm_handle_attach_complete(
|
|||
|
||||
rv = nas_security_encode(&emmbuf, mme_ue, &message);
|
||||
d_assert(rv == CORE_OK && emmbuf, return, "emm build error");
|
||||
d_assert(emm_send_downlink_nas_transport(mme_ue, emmbuf) == CORE_OK,,);
|
||||
d_assert(nas_send_to_downlink_nas_transport(mme_ue, emmbuf) == CORE_OK,,);
|
||||
}
|
||||
|
||||
void emm_handle_identity_request(mme_ue_t *mme_ue)
|
||||
|
@ -258,7 +275,7 @@ void emm_handle_identity_request(mme_ue_t *mme_ue)
|
|||
identity_request->identity_type.type = NAS_IDENTITY_TYPE_2_IMSI;
|
||||
|
||||
d_assert(nas_plain_encode(&emmbuf, &message) == CORE_OK && emmbuf,,);
|
||||
d_assert(emm_send_downlink_nas_transport(mme_ue, emmbuf) == CORE_OK,,);
|
||||
d_assert(nas_send_to_downlink_nas_transport(mme_ue, emmbuf) == CORE_OK,,);
|
||||
}
|
||||
|
||||
void emm_handle_identity_response(
|
||||
|
@ -290,23 +307,6 @@ void emm_handle_identity_response(
|
|||
else
|
||||
{
|
||||
d_warn("Not supported Identity type(%d)", mobile_identity->imsi.type);
|
||||
return;
|
||||
}
|
||||
|
||||
if (SECURITY_CONTEXT_IS_VALID(mme_ue))
|
||||
{
|
||||
emm_handle_attach_accept(mme_ue);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (MME_SESSION_IS_CREATED(mme_ue))
|
||||
{
|
||||
emm_handle_s11_delete_session_request(mme_ue);
|
||||
}
|
||||
else
|
||||
{
|
||||
mme_s6a_send_air(mme_ue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -335,7 +335,7 @@ void emm_handle_authentication_request(mme_ue_t *mme_ue)
|
|||
AUTN_LEN;
|
||||
|
||||
d_assert(nas_plain_encode(&emmbuf, &message) == CORE_OK && emmbuf,,);
|
||||
d_assert(emm_send_downlink_nas_transport(mme_ue, emmbuf) == CORE_OK,,);
|
||||
d_assert(nas_send_to_downlink_nas_transport(mme_ue, emmbuf) == CORE_OK,,);
|
||||
}
|
||||
|
||||
void emm_handle_authentication_response(mme_ue_t *mme_ue,
|
||||
|
@ -430,7 +430,7 @@ void emm_handle_authentication_response(mme_ue_t *mme_ue,
|
|||
|
||||
rv = nas_security_encode(&emmbuf, mme_ue, &message);
|
||||
d_assert(rv == CORE_OK && emmbuf, return, "emm build error");
|
||||
d_assert(emm_send_downlink_nas_transport(mme_ue, emmbuf) == CORE_OK,,);
|
||||
d_assert(nas_send_to_downlink_nas_transport(mme_ue, emmbuf) == CORE_OK,,);
|
||||
}
|
||||
|
||||
void emm_handle_detach_request(
|
||||
|
@ -516,7 +516,7 @@ void emm_handle_detach_accept(
|
|||
|
||||
rv = nas_security_encode(&emmbuf, mme_ue, &message);
|
||||
d_assert(rv == CORE_OK && emmbuf, return, "emm build error");
|
||||
d_assert(emm_send_downlink_nas_transport(mme_ue, emmbuf) == CORE_OK,,);
|
||||
d_assert(nas_send_to_downlink_nas_transport(mme_ue, emmbuf) == CORE_OK,,);
|
||||
}
|
||||
|
||||
cause.present = S1ap_Cause_PR_nas;
|
||||
|
@ -548,7 +548,7 @@ void emm_handle_service_request(
|
|||
rv = s1ap_build_initial_context_setup_request(&s1apbuf, bearer, NULL);
|
||||
d_assert(rv == CORE_OK && s1apbuf, return, "s1ap build error");
|
||||
|
||||
d_assert(emm_send_to_enb(enb_ue, s1apbuf) == CORE_OK,, "s1ap send error");
|
||||
d_assert(nas_send_to_enb(enb_ue, s1apbuf) == CORE_OK,, "s1ap send error");
|
||||
}
|
||||
|
||||
void emm_handle_emm_status(mme_ue_t *mme_ue, nas_emm_status_t *emm_status)
|
||||
|
@ -559,67 +559,9 @@ void emm_handle_emm_status(mme_ue_t *mme_ue, nas_emm_status_t *emm_status)
|
|||
emm_status->emm_cause, mme_ue->imsi_bcd);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ESM Layer in EMM Handler
|
||||
*/
|
||||
void emm_handle_esm_information_request(mme_ue_t *mme_ue)
|
||||
{
|
||||
status_t rv;
|
||||
pkbuf_t *esmbuf = NULL;
|
||||
mme_sess_t *sess = NULL;
|
||||
mme_bearer_t *bearer = NULL;
|
||||
|
||||
d_assert(mme_ue, return, "Null param");
|
||||
sess = emm_sess_find_by_ue(mme_ue);
|
||||
d_assert(sess, return, "Null param");
|
||||
bearer = mme_default_bearer_in_sess(sess);
|
||||
d_assert(bearer, return, "Null param");
|
||||
|
||||
rv = esm_build_information_request(&esmbuf, bearer);
|
||||
d_assert(rv == CORE_OK && esmbuf, return, "esm_build failed");
|
||||
d_assert(emm_send_downlink_nas_transport(mme_ue, esmbuf) == CORE_OK,,);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* S6A Layer in EMM Handler
|
||||
*/
|
||||
void emm_handle_s6a_aia(mme_ue_t *mme_ue, c_uint32_t result_code)
|
||||
{
|
||||
if (result_code != ER_DIAMETER_SUCCESS)
|
||||
{
|
||||
/* TODO */
|
||||
/* Send Attach Reject */
|
||||
return;
|
||||
}
|
||||
|
||||
emm_handle_authentication_request(mme_ue);
|
||||
}
|
||||
|
||||
void emm_handle_s6a_ula(mme_ue_t *mme_ue, c_uint32_t result_code)
|
||||
{
|
||||
if (result_code != ER_DIAMETER_SUCCESS)
|
||||
{
|
||||
/* TODO */
|
||||
return;
|
||||
}
|
||||
|
||||
emm_handle_esm_information_request(mme_ue);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* S11 Layer in EMM Handler
|
||||
*/
|
||||
void emm_handle_s11_create_session_response(mme_sess_t *sess)
|
||||
{
|
||||
d_assert(sess, return, "Null param");
|
||||
|
||||
/* TODO
|
||||
* if PDN connectivity request without Attach Request,
|
||||
* we nned to send without Attach Accept
|
||||
*/
|
||||
d_assert(emm_send_initial_context_setup_request(sess, 1) == CORE_OK,,);
|
||||
}
|
||||
|
||||
void emm_handle_s11_delete_session_request(mme_ue_t *mme_ue)
|
||||
{
|
||||
status_t rv;
|
||||
|
@ -644,182 +586,3 @@ void emm_handle_s11_delete_session_request(mme_ue_t *mme_ue)
|
|||
sess = mme_sess_next(sess);
|
||||
}
|
||||
}
|
||||
|
||||
void emm_handle_s11_delete_session_response(mme_sess_t *sess)
|
||||
{
|
||||
mme_ue_t *mme_ue = NULL;
|
||||
nas_message_t *message = NULL;
|
||||
|
||||
d_assert(sess, return, "Null param");
|
||||
mme_ue = sess->mme_ue;
|
||||
d_assert(mme_ue, return, "Null param");
|
||||
message = &mme_ue->last_emm_message;
|
||||
d_assert(message, return, "Null param");
|
||||
|
||||
mme_sess_remove(sess);
|
||||
|
||||
d_trace(3, "[NAS] Delete Session Response : UE[%s] <-- EMM[%d]\n",
|
||||
mme_ue->imsi_bcd, message->emm.h.message_type);
|
||||
|
||||
switch(message->emm.h.message_type)
|
||||
{
|
||||
case NAS_DETACH_REQUEST:
|
||||
{
|
||||
emm_handle_detach_accept(mme_ue,
|
||||
&message->emm.detach_request_from_ue);
|
||||
break;
|
||||
}
|
||||
case NAS_ATTACH_REQUEST:
|
||||
case NAS_IDENTITY_RESPONSE:
|
||||
{
|
||||
mme_s6a_send_air(mme_ue);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void emm_handle_s11_downlink_data_notification(gtp_xact_t *xact,
|
||||
mme_bearer_t *bearer)
|
||||
{
|
||||
status_t rv;
|
||||
mme_ue_t *mme_ue = NULL;
|
||||
mme_sess_t *sess;
|
||||
pkbuf_t *s11buf = NULL;
|
||||
|
||||
d_assert(xact, return, "Null param");
|
||||
d_assert(bearer, return, "Null param");
|
||||
mme_ue = bearer->mme_ue;
|
||||
d_assert(mme_ue, return, "Null param");
|
||||
|
||||
sess = mme_sess_find_by_ebi(mme_ue, bearer->ebi);
|
||||
d_assert(sess, return, "Null param");
|
||||
|
||||
/* Build Downlink data notification ack */
|
||||
rv = mme_s11_build_downlink_data_notification_ack(&s11buf, sess);
|
||||
d_assert(rv == CORE_OK, return, "S11 build error");
|
||||
|
||||
d_assert(gtp_xact_commit(xact,
|
||||
GTP_DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE_TYPE,
|
||||
sess->sgw_s11_teid, s11buf) == CORE_OK,
|
||||
return , "xact commit error");
|
||||
}
|
||||
|
||||
static status_t emm_send_to_enb(enb_ue_t *enb_ue, pkbuf_t *pkbuf)
|
||||
{
|
||||
mme_enb_t *enb = NULL;
|
||||
|
||||
d_assert(enb_ue, return CORE_ERROR, "Null param");
|
||||
enb = enb_ue->enb;
|
||||
d_assert(enb, return CORE_ERROR, "Null param");
|
||||
|
||||
return s1ap_send_to_enb(enb, pkbuf);
|
||||
}
|
||||
|
||||
static status_t emm_send_downlink_nas_transport(
|
||||
mme_ue_t *mme_ue, pkbuf_t *pkbuf)
|
||||
{
|
||||
status_t rv;
|
||||
pkbuf_t *s1apbuf = NULL;
|
||||
enb_ue_t *enb_ue = NULL;
|
||||
|
||||
enb_ue = mme_ue->enb_ue;
|
||||
d_assert(enb_ue, return CORE_ERROR, "Null param");
|
||||
|
||||
rv = s1ap_build_downlink_nas_transport(&s1apbuf, enb_ue, pkbuf);
|
||||
d_assert(rv == CORE_OK && s1apbuf,
|
||||
pkbuf_free(pkbuf); return CORE_ERROR, "s1ap build error");
|
||||
|
||||
return emm_send_to_enb(enb_ue, s1apbuf);
|
||||
}
|
||||
|
||||
static status_t emm_send_initial_context_setup_request(
|
||||
mme_sess_t *sess, int with_attach_accept)
|
||||
{
|
||||
status_t rv;
|
||||
mme_ue_t *mme_ue = NULL;
|
||||
enb_ue_t *enb_ue = NULL;
|
||||
mme_bearer_t *bearer = NULL;
|
||||
pkbuf_t *esmbuf = NULL, *pkbuf = NULL, *s1apbuf = NULL;
|
||||
|
||||
d_assert(sess, return CORE_ERROR, "Null param");
|
||||
mme_ue = sess->mme_ue;
|
||||
d_assert(mme_ue, return CORE_ERROR, "Null param");
|
||||
enb_ue = mme_ue->enb_ue;
|
||||
d_assert(enb_ue, return CORE_ERROR, "Null param");
|
||||
bearer = mme_default_bearer_in_sess(sess);
|
||||
d_assert(bearer, return CORE_ERROR, "Null param");
|
||||
|
||||
rv = esm_build_activate_default_bearer_context(&pkbuf, bearer);
|
||||
d_assert(rv == CORE_OK && pkbuf, return CORE_ERROR, "bearer build error");
|
||||
|
||||
d_trace(3, "[NAS] Activate default bearer context request : "
|
||||
"EMM <-- ESM[%d]\n", bearer->ebi);
|
||||
|
||||
if (with_attach_accept)
|
||||
{
|
||||
esmbuf = pkbuf;
|
||||
rv = emm_build_attach_accept(&pkbuf, mme_ue, esmbuf);
|
||||
d_assert(rv == CORE_OK && pkbuf,
|
||||
pkbuf_free(esmbuf); return CORE_ERROR, "emm build error");
|
||||
|
||||
d_trace(3, "[NAS] Attach accept : UE[%s] <-- EMM\n", mme_ue->imsi_bcd);
|
||||
}
|
||||
|
||||
rv = s1ap_build_initial_context_setup_request(&s1apbuf, bearer, pkbuf);
|
||||
d_assert(rv == CORE_OK && s1apbuf,
|
||||
pkbuf_free(pkbuf); return CORE_ERROR, "s1ap build error");
|
||||
|
||||
return emm_send_to_enb(enb_ue, s1apbuf);
|
||||
}
|
||||
|
||||
|
||||
static void emm_handle_esm_message_container(
|
||||
mme_ue_t *mme_ue, nas_esm_message_container_t *esm_message_container)
|
||||
{
|
||||
pkbuf_t *esmbuf = NULL;
|
||||
event_t e;
|
||||
|
||||
nas_esm_header_t *h = NULL;
|
||||
c_uint8_t pti = NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED;
|
||||
c_uint8_t ebi = NAS_EPS_BEARER_IDENTITY_UNASSIGNED;
|
||||
mme_bearer_t *bearer = NULL;
|
||||
|
||||
d_assert(mme_ue, return, "Null param");
|
||||
d_assert(esm_message_container, return, "Null param");
|
||||
d_assert(esm_message_container->len, return, "Null param");
|
||||
|
||||
h = (nas_esm_header_t *)esm_message_container->data;
|
||||
d_assert(h, return, "Null param");
|
||||
|
||||
pti = h->procedure_transaction_identity;
|
||||
ebi = h->eps_bearer_identity;
|
||||
if (pti == NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED && ebi)
|
||||
bearer = mme_bearer_find_by_ue_ebi(mme_ue, ebi);
|
||||
else if (ebi == NAS_EPS_BEARER_IDENTITY_UNASSIGNED && pti)
|
||||
bearer = mme_bearer_find_by_ue_pti(mme_ue, pti);
|
||||
|
||||
if (!bearer)
|
||||
bearer = mme_sess_add(mme_ue, pti);
|
||||
d_assert(bearer, return, "No Bearer Context");
|
||||
|
||||
/* The Packet Buffer(pkbuf_t) for NAS message MUST make a HEADROOM.
|
||||
* When calculating AES_CMAC, we need to use the headroom of the packet. */
|
||||
esmbuf = pkbuf_alloc(NAS_HEADROOM, esm_message_container->len);
|
||||
d_assert(esmbuf, return, "Null param");
|
||||
memcpy(esmbuf->payload,
|
||||
esm_message_container->data, esm_message_container->len);
|
||||
|
||||
event_set(&e, MME_EVT_ESM_BEARER_MSG);
|
||||
event_set_param1(&e, (c_uintptr_t)bearer->index);
|
||||
event_set_param3(&e, (c_uintptr_t)esmbuf);
|
||||
mme_event_send(&e);
|
||||
}
|
||||
|
||||
static mme_sess_t *emm_sess_find_by_ue(mme_ue_t *mme_ue)
|
||||
{
|
||||
/* TODO : fix the current transaction from the PDN connectivity request's PTI */
|
||||
return mme_sess_first(mme_ue);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,19 +34,8 @@ CORE_DECLARE(void) emm_handle_service_request(
|
|||
CORE_DECLARE(void) emm_handle_emm_status(
|
||||
mme_ue_t *mme_ue, nas_emm_status_t *emm_status);
|
||||
|
||||
/** ESM Layer in EMM handler */
|
||||
CORE_DECLARE(void) emm_handle_esm_information_request(mme_ue_t *mme_ue);
|
||||
|
||||
/** S6A Layer in EMM handler */
|
||||
CORE_DECLARE(void) emm_handle_s6a_aia(mme_ue_t *mme_ue, c_uint32_t result_code);
|
||||
CORE_DECLARE(void) emm_handle_s6a_ula(mme_ue_t *mme_ue, c_uint32_t result_code);
|
||||
|
||||
/** S11 Layer in EMM handler */
|
||||
CORE_DECLARE(void) emm_handle_s11_create_session_response(mme_sess_t *sess);
|
||||
CORE_DECLARE(void) emm_handle_s11_delete_session_request(mme_ue_t *mme_ue);
|
||||
CORE_DECLARE(void) emm_handle_s11_delete_session_response(mme_sess_t *sess);
|
||||
CORE_DECLARE(void) emm_handle_s11_downlink_data_notification(gtp_xact_t *xact,
|
||||
mme_bearer_t *bearer);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
170
src/mme/emm_sm.c
170
src/mme/emm_sm.c
|
@ -3,13 +3,17 @@
|
|||
#include "core_debug.h"
|
||||
|
||||
#include "nas_message.h"
|
||||
#include "fd_lib.h"
|
||||
|
||||
#include "mme_event.h"
|
||||
#include "emm_handler.h"
|
||||
#include "emm_build.h"
|
||||
#include "mme_s6a_handler.h"
|
||||
#include "mme_kdf.h"
|
||||
#include "s1ap_handler.h"
|
||||
#include "mme_s6a_handler.h"
|
||||
#include "emm_handler.h"
|
||||
#include "emm_build.h"
|
||||
#include "esm_handler.h"
|
||||
#include "mme_s11_build.h"
|
||||
#include "mme_s11_path.h"
|
||||
|
||||
void emm_state_initial(fsm_t *s, event_t *e)
|
||||
{
|
||||
|
@ -58,13 +62,79 @@ void emm_state_operational(fsm_t *s, event_t *e)
|
|||
case S6A_CMD_AUTHENTICATION_INFORMATION:
|
||||
{
|
||||
c_uint32_t result_code = event_get_param3(e);
|
||||
emm_handle_s6a_aia(mme_ue, result_code);
|
||||
if (result_code != ER_DIAMETER_SUCCESS)
|
||||
{
|
||||
/* TODO */
|
||||
/* Send Attach Reject */
|
||||
return;
|
||||
}
|
||||
|
||||
emm_handle_authentication_request(mme_ue);
|
||||
break;
|
||||
}
|
||||
case S6A_CMD_UPDATE_LOCATION:
|
||||
{
|
||||
nas_message_t *message = NULL;
|
||||
c_uint32_t result_code = event_get_param3(e);
|
||||
emm_handle_s6a_ula(mme_ue, result_code);
|
||||
if (result_code != ER_DIAMETER_SUCCESS)
|
||||
{
|
||||
/* TODO */
|
||||
return;
|
||||
}
|
||||
|
||||
message = &mme_ue->last_esm_message;
|
||||
d_assert(message, return, "Null param");
|
||||
|
||||
switch(message->esm.h.message_type)
|
||||
{
|
||||
case NAS_PDN_CONNECTIVITY_REQUEST:
|
||||
{
|
||||
mme_bearer_t *bearer = NULL;
|
||||
mme_sess_t *sess = NULL;
|
||||
|
||||
bearer = mme_bearer_find_by_ue_pti(mme_ue,
|
||||
message->esm.h.procedure_transaction_identity);
|
||||
d_assert(bearer, return, "Null param(pti:%d)",
|
||||
message->esm.h.procedure_transaction_identity);
|
||||
sess = bearer->sess;
|
||||
d_assert(sess, return, "Null param");
|
||||
|
||||
if (MME_SESSION_HAVE_APN(sess))
|
||||
{
|
||||
if (MME_SESSION_IS_CREATED(mme_ue))
|
||||
{
|
||||
emm_handle_attach_accept(mme_ue);
|
||||
}
|
||||
else
|
||||
{
|
||||
status_t rv;
|
||||
pkbuf_t *pkbuf = NULL;
|
||||
|
||||
rv = mme_s11_build_create_session_request(
|
||||
&pkbuf, bearer);
|
||||
d_assert(rv == CORE_OK, return,
|
||||
"S11 build error");
|
||||
|
||||
rv = mme_s11_send_to_sgw(bearer->sgw,
|
||||
GTP_CREATE_SESSION_REQUEST_TYPE,
|
||||
0, pkbuf);
|
||||
d_assert(rv == CORE_OK, return,
|
||||
"S11 send error");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
esm_handle_information_request(mme_ue);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -92,6 +162,12 @@ void emm_state_operational(fsm_t *s, event_t *e)
|
|||
mme_ue_paged(mme_ue);
|
||||
emm_handle_service_request(
|
||||
mme_ue, &message->emm.service_request);
|
||||
|
||||
/* Update Kenb */
|
||||
if (SECURITY_CONTEXT_IS_VALID(mme_ue))
|
||||
mme_kdf_enb(mme_ue->kasme, mme_ue->ul_count.i32,
|
||||
mme_ue->kenb);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -102,12 +178,96 @@ void emm_state_operational(fsm_t *s, event_t *e)
|
|||
mme_ue_paged(mme_ue);
|
||||
emm_handle_attach_request(
|
||||
mme_ue, &message->emm.attach_request);
|
||||
|
||||
/* Update Kenb */
|
||||
if (SECURITY_CONTEXT_IS_VALID(mme_ue))
|
||||
mme_kdf_enb(mme_ue->kasme, mme_ue->ul_count.i32,
|
||||
mme_ue->kenb);
|
||||
break;
|
||||
}
|
||||
case NAS_IDENTITY_RESPONSE:
|
||||
{
|
||||
emm_handle_identity_response(mme_ue,
|
||||
&message->emm.identity_response);
|
||||
|
||||
if (!MME_UE_HAVE_IMSI(mme_ue))
|
||||
{
|
||||
d_error("Cannot find IMSI");
|
||||
break;
|
||||
}
|
||||
|
||||
if (SECURITY_CONTEXT_IS_VALID(mme_ue))
|
||||
{
|
||||
emm_handle_attach_accept(mme_ue);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (MME_SESSION_IS_CREATED(mme_ue))
|
||||
{
|
||||
emm_handle_s11_delete_session_request(mme_ue);
|
||||
}
|
||||
else
|
||||
{
|
||||
mme_s6a_send_air(mme_ue);
|
||||
}
|
||||
#if 0
|
||||
nas_message_t *message = NULL;
|
||||
message = &mme_ue->last_esm_message;
|
||||
d_assert(message, return, "Null param");
|
||||
|
||||
switch(message->esm.h.message_type)
|
||||
{
|
||||
case NAS_PDN_CONNECTIVITY_REQUEST:
|
||||
{
|
||||
mme_bearer_t *bearer = NULL;
|
||||
mme_sess_t *sess = NULL;
|
||||
|
||||
bearer = mme_bearer_find_by_ue_pti(mme_ue,
|
||||
message->esm.h.procedure_transaction_identity);
|
||||
d_assert(bearer, return, "Null param(pti:%d)",
|
||||
message->esm.h.procedure_transaction_identity);
|
||||
sess = bearer->sess;
|
||||
d_assert(sess, return, "Null param");
|
||||
|
||||
if (MME_SESSION_HAVE_APN(sess))
|
||||
{
|
||||
if (MME_SESSION_IS_CREATED(mme_ue))
|
||||
{
|
||||
emm_handle_attach_accept(mme_ue);
|
||||
}
|
||||
else
|
||||
{
|
||||
status_t rv;
|
||||
pkbuf_t *pkbuf = NULL;
|
||||
|
||||
rv = mme_s11_build_create_session_request(
|
||||
&pkbuf, bearer);
|
||||
d_assert(rv == CORE_OK, return,
|
||||
"S11 build error");
|
||||
|
||||
rv = mme_s11_send_to_sgw(bearer->sgw,
|
||||
GTP_CREATE_SESSION_REQUEST_TYPE,
|
||||
0, pkbuf);
|
||||
d_assert(rv == CORE_OK, return,
|
||||
"S11 send error");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
esm_handle_information_request(mme_ue);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case NAS_AUTHENTICATION_RESPONSE:
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "esm_build.h"
|
||||
#include "s1ap_build.h"
|
||||
#include "s1ap_path.h"
|
||||
#include "nas_path.h"
|
||||
#include "mme_s11_build.h"
|
||||
#include "mme_s11_path.h"
|
||||
|
||||
|
@ -28,6 +29,25 @@ void esm_handle_pdn_connectivity_request(mme_bearer_t *bearer,
|
|||
}
|
||||
}
|
||||
|
||||
void esm_handle_information_request(mme_ue_t *mme_ue)
|
||||
{
|
||||
status_t rv;
|
||||
pkbuf_t *esmbuf = NULL;
|
||||
mme_sess_t *sess = NULL;
|
||||
mme_bearer_t *bearer = NULL;
|
||||
|
||||
d_assert(mme_ue, return, "Null param");
|
||||
sess = mme_sess_first(mme_ue);
|
||||
d_assert(sess, return, "Null param");
|
||||
bearer = mme_default_bearer_in_sess(sess);
|
||||
d_assert(bearer, return, "Null param");
|
||||
|
||||
rv = esm_build_information_request(&esmbuf, bearer);
|
||||
d_assert(rv == CORE_OK && esmbuf, return, "esm_build failed");
|
||||
d_assert(nas_send_to_downlink_nas_transport(mme_ue, esmbuf) == CORE_OK,,);
|
||||
}
|
||||
|
||||
|
||||
void esm_handle_information_response(mme_bearer_t *bearer,
|
||||
nas_esm_information_response_t *esm_information_response)
|
||||
{
|
||||
|
|
|
@ -11,6 +11,7 @@ extern "C" {
|
|||
|
||||
CORE_DECLARE(void) esm_handle_pdn_connectivity_request(mme_bearer_t *bearer,
|
||||
nas_pdn_connectivity_request_t *pdn_connectivity_request);
|
||||
CORE_DECLARE(void) esm_handle_information_request(mme_ue_t *mme_ue);
|
||||
CORE_DECLARE(void) esm_handle_information_response(mme_bearer_t *bearer,
|
||||
nas_esm_information_response_t *bearer_information_response);
|
||||
|
||||
|
|
|
@ -5,8 +5,12 @@
|
|||
#include "nas_message.h"
|
||||
|
||||
#include "mme_event.h"
|
||||
#include "esm_handler.h"
|
||||
#include "mme_s6a_handler.h"
|
||||
#include "emm_handler.h"
|
||||
#include "esm_build.h"
|
||||
#include "esm_handler.h"
|
||||
#include "mme_s11_build.h"
|
||||
#include "mme_s11_path.h"
|
||||
|
||||
void esm_state_initial(fsm_t *s, event_t *e)
|
||||
{
|
||||
|
@ -68,6 +72,59 @@ void esm_state_operational(fsm_t *s, event_t *e)
|
|||
d_trace(3, "[NAS] PDN connectivity request : "
|
||||
"UE[%s] --> ESM[%d]\n",
|
||||
mme_ue->imsi_bcd, bearer->pti);
|
||||
|
||||
if (MME_UE_HAVE_IMSI(mme_ue))
|
||||
{
|
||||
/* Known GUTI */
|
||||
if (SECURITY_CONTEXT_IS_VALID(mme_ue))
|
||||
{
|
||||
mme_sess_t *sess = bearer->sess;
|
||||
d_assert(sess, return, "Null param");
|
||||
|
||||
if (MME_SESSION_HAVE_APN(sess))
|
||||
{
|
||||
status_t rv;
|
||||
pkbuf_t *pkbuf = NULL;
|
||||
|
||||
if (MME_SESSION_IS_CREATED(mme_ue))
|
||||
{
|
||||
emm_handle_attach_accept(mme_ue);
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = mme_s11_build_create_session_request(
|
||||
&pkbuf, bearer);
|
||||
d_assert(rv == CORE_OK, return,
|
||||
"S11 build error");
|
||||
|
||||
rv = mme_s11_send_to_sgw(bearer->sgw,
|
||||
GTP_CREATE_SESSION_REQUEST_TYPE,
|
||||
0, pkbuf);
|
||||
d_assert(rv == CORE_OK, return,
|
||||
"S11 send error");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
esm_handle_information_request(mme_ue);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (MME_SESSION_IS_CREATED(mme_ue))
|
||||
{
|
||||
emm_handle_s11_delete_session_request(mme_ue);
|
||||
}
|
||||
else
|
||||
{
|
||||
mme_s6a_send_air(mme_ue);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Continue with Identity Response */
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NAS_ESM_INFORMATION_RESPONSE:
|
||||
|
|
|
@ -257,6 +257,10 @@ typedef struct _mme_sess_t {
|
|||
c_uint32_t sgw_s11_teid;
|
||||
c_uint32_t sgw_s11_addr;
|
||||
|
||||
#define MME_SESSION_HAVE_APN(sess) \
|
||||
((sess) && \
|
||||
(mme_default_bearer_in_sess(sess)) && \
|
||||
(mme_default_bearer_in_sess(sess)->pdn))
|
||||
/* mme_bearer_first(sess) : Default Bearer Context */
|
||||
list_t bearer_list;
|
||||
|
||||
|
|
|
@ -96,6 +96,8 @@ void mme_s11_handle_delete_session_response(
|
|||
return;
|
||||
}
|
||||
|
||||
mme_sess_remove(sess);
|
||||
|
||||
d_trace(3, "[GTP] Delete Session Response : "
|
||||
"MME[%d] <-- SGW[%d]\n", sess->mme_s11_teid, sess->sgw_s11_teid);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "s1ap_handler.h"
|
||||
#include "s1ap_path.h"
|
||||
#include "mme_s6a_handler.h"
|
||||
#include "nas_security.h"
|
||||
#include "emm_handler.h"
|
||||
#include "mme_s11_path.h"
|
||||
|
@ -290,19 +291,57 @@ void mme_state_operational(fsm_t *s, event_t *e)
|
|||
switch(type)
|
||||
{
|
||||
case GTP_CREATE_SESSION_RESPONSE_TYPE:
|
||||
{
|
||||
mme_ue_t *mme_ue = NULL;
|
||||
|
||||
mme_s11_handle_create_session_response(
|
||||
sess, >p_message.create_session_response);
|
||||
emm_handle_s11_create_session_response(sess);
|
||||
|
||||
/* TODO : E_RABSetupRequest */
|
||||
|
||||
mme_ue = sess->mme_ue;
|
||||
d_assert(mme_ue, break, "Null param");
|
||||
|
||||
emm_handle_attach_accept(mme_ue);
|
||||
break;
|
||||
}
|
||||
case GTP_MODIFY_BEARER_RESPONSE_TYPE:
|
||||
mme_s11_handle_modify_bearer_response(
|
||||
sess, >p_message.modify_bearer_response);
|
||||
break;
|
||||
case GTP_DELETE_SESSION_RESPONSE_TYPE:
|
||||
{
|
||||
mme_ue_t *mme_ue = NULL;
|
||||
nas_message_t *message = NULL;
|
||||
|
||||
d_assert(sess, break, "Null param");
|
||||
mme_ue = sess->mme_ue;
|
||||
d_assert(mme_ue, break, "Null param");
|
||||
message = &mme_ue->last_emm_message;
|
||||
d_assert(message, break, "Null param");
|
||||
|
||||
mme_s11_handle_delete_session_response(
|
||||
sess, >p_message.delete_session_response);
|
||||
emm_handle_s11_delete_session_response(sess);
|
||||
|
||||
switch(message->emm.h.message_type)
|
||||
{
|
||||
case NAS_DETACH_REQUEST:
|
||||
{
|
||||
emm_handle_detach_accept(mme_ue,
|
||||
&message->emm.detach_request_from_ue);
|
||||
break;
|
||||
}
|
||||
case NAS_ATTACH_REQUEST:
|
||||
case NAS_IDENTITY_RESPONSE:
|
||||
{
|
||||
mme_s6a_send_air(mme_ue);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GTP_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE:
|
||||
{
|
||||
mme_ue_t *mme_ue = NULL;
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
#include "nas_message.h"
|
||||
#include "nas_security.h"
|
||||
#include "mme_kdf.h"
|
||||
|
||||
status_t nas_security_encode(
|
||||
pkbuf_t **pkbuf, mme_ue_t *mme_ue, nas_message_t *message)
|
||||
|
@ -155,10 +154,6 @@ status_t nas_security_decode(mme_ue_t *mme_ue,
|
|||
mme_ue->mac_failed = 1;
|
||||
}
|
||||
|
||||
/* Update Kenb */
|
||||
if (SECURITY_CONTEXT_IS_VALID(mme_ue))
|
||||
mme_kdf_enb(mme_ue->kasme, mme_ue->ul_count.i32, mme_ue->kenb);
|
||||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue