2020-06-17 05:22:28 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
|
|
|
|
*
|
|
|
|
* This file is part of Open5GS.
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU Affero General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "namf-handler.h"
|
2020-07-29 02:35:43 +00:00
|
|
|
#include "nsmf-handler.h"
|
2020-06-17 05:22:28 +00:00
|
|
|
|
|
|
|
#include "nas-path.h"
|
2020-07-31 02:10:20 +00:00
|
|
|
#include "ngap-path.h"
|
2020-08-07 15:57:17 +00:00
|
|
|
#include "sbi-path.h"
|
2020-06-17 05:22:28 +00:00
|
|
|
|
|
|
|
int amf_namf_comm_handle_n1_n2_message_transfer(
|
2020-11-27 02:44:37 +00:00
|
|
|
ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg)
|
2020-06-17 05:22:28 +00:00
|
|
|
{
|
|
|
|
int status;
|
|
|
|
|
|
|
|
amf_ue_t *amf_ue = NULL;
|
|
|
|
amf_sess_t *sess = NULL;
|
|
|
|
|
2021-01-18 16:48:35 +00:00
|
|
|
ogs_pkbuf_t *n1buf = NULL;
|
|
|
|
ogs_pkbuf_t *n2buf = NULL;
|
2020-06-17 05:22:28 +00:00
|
|
|
|
2020-07-31 02:10:20 +00:00
|
|
|
ogs_pkbuf_t *gmmbuf = NULL;
|
|
|
|
ogs_pkbuf_t *ngapbuf = NULL;
|
|
|
|
|
2020-06-17 05:22:28 +00:00
|
|
|
char *supi = NULL;
|
|
|
|
uint8_t pdu_session_id = OGS_NAS_PDU_SESSION_IDENTITY_UNASSIGNED;
|
|
|
|
|
|
|
|
ogs_sbi_message_t sendmsg;
|
|
|
|
ogs_sbi_response_t *response = NULL;
|
|
|
|
|
|
|
|
OpenAPI_n1_n2_message_transfer_req_data_t *N1N2MessageTransferReqData;
|
|
|
|
OpenAPI_n1_n2_message_transfer_rsp_data_t N1N2MessageTransferRspData;
|
|
|
|
OpenAPI_n1_message_container_t *n1MessageContainer = NULL;
|
|
|
|
OpenAPI_ref_to_binary_data_t *n1MessageContent = NULL;
|
|
|
|
OpenAPI_n2_info_container_t *n2InfoContainer = NULL;
|
|
|
|
OpenAPI_n2_sm_information_t *smInfo = NULL;
|
|
|
|
OpenAPI_n2_info_content_t *n2InfoContent = NULL;
|
|
|
|
OpenAPI_ref_to_binary_data_t *ngapData = NULL;
|
|
|
|
|
2021-11-16 23:09:16 +00:00
|
|
|
OpenAPI_ngap_ie_type_e ngapIeType = OpenAPI_ngap_ie_type_NULL;
|
|
|
|
|
2020-11-27 02:44:37 +00:00
|
|
|
ogs_assert(stream);
|
2020-06-17 05:22:28 +00:00
|
|
|
ogs_assert(recvmsg);
|
|
|
|
|
|
|
|
N1N2MessageTransferReqData = recvmsg->N1N2MessageTransferReqData;
|
|
|
|
if (!N1N2MessageTransferReqData) {
|
|
|
|
ogs_error("No N1N2MessageTransferReqData");
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
|
2021-07-16 08:02:33 +00:00
|
|
|
if (N1N2MessageTransferReqData->is_pdu_session_id == false) {
|
2020-06-17 05:22:28 +00:00
|
|
|
ogs_error("No PDU Session Identity");
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
2021-07-16 08:02:33 +00:00
|
|
|
pdu_session_id = N1N2MessageTransferReqData->pdu_session_id;
|
2020-06-17 05:22:28 +00:00
|
|
|
|
|
|
|
supi = recvmsg->h.resource.component[1];
|
|
|
|
if (!supi) {
|
|
|
|
ogs_error("No SUPI");
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
amf_ue = amf_ue_find_by_supi(supi);
|
|
|
|
if (!amf_ue) {
|
|
|
|
ogs_error("No UE context [%s]", supi);
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
sess = amf_sess_find_by_psi(amf_ue, pdu_session_id);
|
|
|
|
if (!sess) {
|
|
|
|
ogs_error("[%s] No PDU Session Context [%d]",
|
|
|
|
amf_ue->supi, pdu_session_id);
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
|
2021-01-18 16:48:35 +00:00
|
|
|
n1MessageContainer = N1N2MessageTransferReqData->n1_message_container;
|
|
|
|
if (n1MessageContainer) {
|
|
|
|
n1MessageContent = n1MessageContainer->n1_message_content;
|
|
|
|
if (!n1MessageContent || !n1MessageContent->content_id) {
|
|
|
|
ogs_error("No n1MessageContent");
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
n1buf = ogs_sbi_find_part_by_content_id(
|
|
|
|
recvmsg, n1MessageContent->content_id);
|
|
|
|
if (!n1buf) {
|
|
|
|
ogs_error("[%s] No N1 SM Content", amf_ue->supi);
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* NOTE : The pkbuf created in the SBI message will be removed
|
|
|
|
* from ogs_sbi_message_free(), so it must be copied.
|
|
|
|
*/
|
|
|
|
n1buf = ogs_pkbuf_copy(n1buf);
|
|
|
|
ogs_assert(n1buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
n2InfoContainer = N1N2MessageTransferReqData->n2_info_container;
|
|
|
|
if (n2InfoContainer) {
|
|
|
|
smInfo = n2InfoContainer->sm_info;
|
|
|
|
if (!smInfo) {
|
|
|
|
ogs_error("No smInfo");
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
2021-11-16 23:09:16 +00:00
|
|
|
|
2021-01-18 16:48:35 +00:00
|
|
|
n2InfoContent = smInfo->n2_info_content;
|
|
|
|
if (!n2InfoContent) {
|
|
|
|
ogs_error("No n2InfoContent");
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
|
2021-11-16 23:09:16 +00:00
|
|
|
ngapIeType = n2InfoContent->ngap_ie_type;
|
|
|
|
|
2021-01-18 16:48:35 +00:00
|
|
|
ngapData = n2InfoContent->ngap_data;
|
|
|
|
if (!ngapData || !ngapData->content_id) {
|
|
|
|
ogs_error("No ngapData");
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
n2buf = ogs_sbi_find_part_by_content_id(
|
|
|
|
recvmsg, ngapData->content_id);
|
|
|
|
if (!n2buf) {
|
|
|
|
ogs_error("[%s] No N2 SM Content", amf_ue->supi);
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* NOTE : The pkbuf created in the SBI message will be removed
|
|
|
|
* from ogs_sbi_message_free(), so it must be copied.
|
|
|
|
*/
|
|
|
|
n2buf = ogs_pkbuf_copy(n2buf);
|
|
|
|
ogs_assert(n2buf);
|
2020-06-17 05:22:28 +00:00
|
|
|
}
|
|
|
|
|
2021-01-18 16:48:35 +00:00
|
|
|
memset(&sendmsg, 0, sizeof(sendmsg));
|
2020-06-17 05:22:28 +00:00
|
|
|
|
2021-01-01 02:07:08 +00:00
|
|
|
status = OGS_SBI_HTTP_STATUS_OK;
|
2020-07-31 02:10:20 +00:00
|
|
|
|
2021-01-18 16:48:35 +00:00
|
|
|
memset(&N1N2MessageTransferRspData, 0, sizeof(N1N2MessageTransferRspData));
|
|
|
|
N1N2MessageTransferRspData.cause =
|
|
|
|
OpenAPI_n1_n2_message_transfer_cause_N1_N2_TRANSFER_INITIATED;
|
|
|
|
|
|
|
|
sendmsg.N1N2MessageTransferRspData = &N1N2MessageTransferRspData;
|
2020-07-31 02:10:20 +00:00
|
|
|
|
2021-11-16 23:09:16 +00:00
|
|
|
switch (ngapIeType) {
|
2021-01-01 02:07:08 +00:00
|
|
|
case OpenAPI_ngap_ie_type_PDU_RES_SETUP_REQ:
|
2021-01-18 16:48:35 +00:00
|
|
|
if (!n2buf) {
|
|
|
|
ogs_error("[%s] No N2 SM Content", amf_ue->supi);
|
|
|
|
return OGS_ERROR;
|
2021-01-01 02:07:08 +00:00
|
|
|
}
|
2020-07-31 02:10:20 +00:00
|
|
|
|
2021-11-14 12:07:56 +00:00
|
|
|
if (n1buf) {
|
|
|
|
gmmbuf = gmm_build_dl_nas_transport(sess,
|
|
|
|
OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, n1buf, 0, 0);
|
|
|
|
ogs_assert(gmmbuf);
|
|
|
|
}
|
|
|
|
|
2021-01-18 16:48:35 +00:00
|
|
|
if (gmmbuf) {
|
|
|
|
ran_ue_t *ran_ue = NULL;
|
|
|
|
|
|
|
|
/***********************************
|
|
|
|
* 4.3.2 PDU Session Establishment *
|
|
|
|
***********************************/
|
|
|
|
|
|
|
|
ran_ue = ran_ue_cycle(amf_ue->ran_ue);
|
|
|
|
ogs_assert(ran_ue);
|
|
|
|
|
|
|
|
if (sess->pdu_session_establishment_accept) {
|
|
|
|
ogs_pkbuf_free(sess->pdu_session_establishment_accept);
|
|
|
|
sess->pdu_session_establishment_accept = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ran_ue->initial_context_setup_request_sent == true) {
|
|
|
|
ngapbuf = ngap_sess_build_pdu_session_resource_setup_request(
|
|
|
|
sess, gmmbuf, n2buf);
|
|
|
|
ogs_assert(ngapbuf);
|
|
|
|
} else {
|
|
|
|
ngapbuf = ngap_sess_build_initial_context_setup_request(
|
|
|
|
sess, gmmbuf, n2buf);
|
|
|
|
ogs_assert(ngapbuf);
|
|
|
|
|
|
|
|
ran_ue->initial_context_setup_request_sent = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (SESSION_CONTEXT_IN_SMF(sess)) {
|
|
|
|
/*
|
|
|
|
* [1-CLIENT] /nsmf-pdusession/v1/sm-contexts
|
|
|
|
* [2-SERVER] /namf-comm/v1/ue-contexts/{supi}/n1-n2-messages
|
|
|
|
*
|
|
|
|
* If [2-SERVER] arrives after [1-CLIENT],
|
|
|
|
* sm-context-ref is created in [1-CLIENT].
|
|
|
|
* So, the PDU session establishment accpet can be transmitted.
|
|
|
|
*/
|
|
|
|
if (nas_5gs_send_to_gnb(amf_ue, ngapbuf) != OGS_OK)
|
|
|
|
ogs_error("nas_5gs_send_to_gnb() failed");
|
|
|
|
} else {
|
|
|
|
sess->pdu_session_establishment_accept = ngapbuf;
|
|
|
|
}
|
|
|
|
|
2021-01-08 03:26:06 +00:00
|
|
|
} else {
|
2021-01-18 16:48:35 +00:00
|
|
|
/*********************************************
|
|
|
|
* 4.2.3.3 Network Triggered Service Request *
|
|
|
|
*********************************************/
|
|
|
|
|
|
|
|
if (CM_IDLE(amf_ue)) {
|
|
|
|
ogs_sbi_server_t *server = NULL;
|
|
|
|
ogs_sbi_header_t header;
|
|
|
|
ogs_sbi_client_t *client = NULL;
|
|
|
|
ogs_sockaddr_t *addr = NULL;
|
|
|
|
|
|
|
|
if (!N1N2MessageTransferReqData->n1n2_failure_txf_notif_uri) {
|
|
|
|
ogs_error("[%s:%d] No n1-n2-failure-notification-uri",
|
|
|
|
amf_ue->supi, sess->psi);
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
addr = ogs_sbi_getaddr_from_uri(
|
|
|
|
N1N2MessageTransferReqData->n1n2_failure_txf_notif_uri);
|
|
|
|
if (!addr) {
|
|
|
|
ogs_error("[%s:%d] Invalid URI [%s]",
|
|
|
|
amf_ue->supi, sess->psi,
|
|
|
|
N1N2MessageTransferReqData->
|
|
|
|
n1n2_failure_txf_notif_uri);
|
|
|
|
return OGS_ERROR;;
|
|
|
|
}
|
|
|
|
|
|
|
|
client = ogs_sbi_client_find(addr);
|
|
|
|
if (!client) {
|
|
|
|
client = ogs_sbi_client_add(addr);
|
|
|
|
ogs_assert(client);
|
|
|
|
}
|
2022-04-10 11:09:27 +00:00
|
|
|
OGS_SBI_SETUP_CLIENT(&sess->paging, client);
|
2021-01-18 16:48:35 +00:00
|
|
|
|
|
|
|
ogs_freeaddrinfo(addr);
|
|
|
|
|
|
|
|
status = OGS_SBI_HTTP_STATUS_ACCEPTED;
|
|
|
|
N1N2MessageTransferRspData.cause =
|
|
|
|
OpenAPI_n1_n2_message_transfer_cause_ATTEMPTING_TO_REACH_UE;
|
|
|
|
|
|
|
|
/* Location */
|
|
|
|
server = ogs_sbi_server_from_stream(stream);
|
|
|
|
ogs_assert(server);
|
|
|
|
|
|
|
|
memset(&header, 0, sizeof(header));
|
|
|
|
header.service.name = (char *)OGS_SBI_SERVICE_NAME_NAMF_COMM;
|
|
|
|
header.api.version = (char *)OGS_SBI_API_V1;
|
|
|
|
header.resource.component[0] =
|
|
|
|
(char *)OGS_SBI_RESOURCE_NAME_UE_CONTEXTS;
|
|
|
|
header.resource.component[1] = amf_ue->supi;
|
|
|
|
header.resource.component[2] =
|
|
|
|
(char *)OGS_SBI_RESOURCE_NAME_N1_N2_MESSAGES;
|
|
|
|
header.resource.component[3] = sess->sm_context_ref;
|
|
|
|
|
|
|
|
sendmsg.http.location = ogs_sbi_server_uri(server, &header);
|
|
|
|
|
|
|
|
/* Store Paging Info */
|
|
|
|
AMF_SESS_STORE_PAGING_INFO(
|
|
|
|
sess, sendmsg.http.location,
|
|
|
|
N1N2MessageTransferReqData->n1n2_failure_txf_notif_uri);
|
|
|
|
|
|
|
|
/* Store N2 Transfer message */
|
|
|
|
AMF_SESS_STORE_N2_TRANSFER(
|
|
|
|
sess, pdu_session_resource_setup_request, n2buf);
|
|
|
|
|
2021-06-06 13:35:46 +00:00
|
|
|
ogs_assert(OGS_OK == ngap_send_paging(amf_ue));
|
2021-01-18 16:48:35 +00:00
|
|
|
|
|
|
|
} else if (CM_CONNECTED(amf_ue)) {
|
2021-05-16 03:22:10 +00:00
|
|
|
ogs_assert(OGS_OK ==
|
|
|
|
ngap_send_pdu_resource_setup_request(sess, n2buf));
|
2021-01-18 16:48:35 +00:00
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
ogs_fatal("[%s] Invalid AMF-UE state", amf_ue->supi);
|
|
|
|
ogs_assert_if_reached();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
break;
|
2021-01-08 03:26:06 +00:00
|
|
|
|
2021-01-18 16:48:35 +00:00
|
|
|
case OpenAPI_ngap_ie_type_PDU_RES_MOD_REQ:
|
2021-11-14 12:07:56 +00:00
|
|
|
if (!n1buf) {
|
2021-01-18 16:48:35 +00:00
|
|
|
ogs_error("[%s] No N1 SM Content", amf_ue->supi);
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
if (!n2buf) {
|
|
|
|
ogs_error("[%s] No N2 SM Content", amf_ue->supi);
|
|
|
|
return OGS_ERROR;
|
2021-01-08 03:26:06 +00:00
|
|
|
}
|
2021-01-01 02:07:08 +00:00
|
|
|
|
2021-01-18 16:48:35 +00:00
|
|
|
if (CM_IDLE(amf_ue)) {
|
2021-11-14 12:07:56 +00:00
|
|
|
ogs_sbi_server_t *server = NULL;
|
|
|
|
ogs_sbi_header_t header;
|
|
|
|
|
|
|
|
status = OGS_SBI_HTTP_STATUS_ACCEPTED;
|
|
|
|
N1N2MessageTransferRspData.cause =
|
|
|
|
OpenAPI_n1_n2_message_transfer_cause_ATTEMPTING_TO_REACH_UE;
|
|
|
|
|
|
|
|
/* Location */
|
|
|
|
server = ogs_sbi_server_from_stream(stream);
|
|
|
|
ogs_assert(server);
|
|
|
|
|
|
|
|
memset(&header, 0, sizeof(header));
|
|
|
|
header.service.name = (char *)OGS_SBI_SERVICE_NAME_NAMF_COMM;
|
|
|
|
header.api.version = (char *)OGS_SBI_API_V1;
|
|
|
|
header.resource.component[0] =
|
|
|
|
(char *)OGS_SBI_RESOURCE_NAME_UE_CONTEXTS;
|
|
|
|
header.resource.component[1] = amf_ue->supi;
|
|
|
|
header.resource.component[2] =
|
|
|
|
(char *)OGS_SBI_RESOURCE_NAME_N1_N2_MESSAGES;
|
|
|
|
header.resource.component[3] = sess->sm_context_ref;
|
|
|
|
|
|
|
|
sendmsg.http.location = ogs_sbi_server_uri(server, &header);
|
|
|
|
|
|
|
|
/* Store Paging Info */
|
|
|
|
AMF_SESS_STORE_PAGING_INFO(
|
|
|
|
sess, sendmsg.http.location, NULL);
|
|
|
|
|
|
|
|
/* Store 5GSM Message */
|
|
|
|
AMF_SESS_STORE_5GSM_MESSAGE(sess,
|
|
|
|
OGS_NAS_5GS_PDU_SESSION_MODIFICATION_COMMAND,
|
|
|
|
n1buf, n2buf);
|
|
|
|
|
|
|
|
ogs_assert(OGS_OK == ngap_send_paging(amf_ue));
|
2021-01-18 16:48:35 +00:00
|
|
|
|
|
|
|
} else if (CM_CONNECTED(amf_ue)) {
|
2021-11-14 12:07:56 +00:00
|
|
|
gmmbuf = gmm_build_dl_nas_transport(sess,
|
|
|
|
OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, n1buf, 0, 0);
|
|
|
|
ogs_assert(gmmbuf);
|
|
|
|
|
2021-01-18 16:48:35 +00:00
|
|
|
ngapbuf = ngap_build_pdu_session_resource_modify_request(
|
|
|
|
sess, gmmbuf, n2buf);
|
|
|
|
ogs_assert(ngapbuf);
|
|
|
|
|
|
|
|
if (nas_5gs_send_to_gnb(amf_ue, ngapbuf) != OGS_OK)
|
2021-01-01 02:07:08 +00:00
|
|
|
ogs_error("nas_5gs_send_to_gnb() failed");
|
2021-01-18 16:48:35 +00:00
|
|
|
|
2021-01-01 02:07:08 +00:00
|
|
|
} else {
|
2021-01-18 16:48:35 +00:00
|
|
|
ogs_fatal("[%s] Invalid AMF-UE state", amf_ue->supi);
|
|
|
|
ogs_assert_if_reached();
|
2021-01-01 02:07:08 +00:00
|
|
|
}
|
2021-01-18 16:48:35 +00:00
|
|
|
|
2021-01-01 02:07:08 +00:00
|
|
|
break;
|
|
|
|
|
2021-01-18 16:48:35 +00:00
|
|
|
case OpenAPI_ngap_ie_type_PDU_RES_REL_CMD:
|
|
|
|
if (!n2buf) {
|
|
|
|
ogs_error("[%s] No N2 SM Content", amf_ue->supi);
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
|
2021-11-14 12:07:56 +00:00
|
|
|
if (n1buf)
|
|
|
|
ogs_pkbuf_free(n1buf);
|
|
|
|
|
2021-01-18 16:48:35 +00:00
|
|
|
if (CM_IDLE(amf_ue)) {
|
|
|
|
if (n2buf)
|
|
|
|
ogs_pkbuf_free(n2buf);
|
|
|
|
|
2021-07-16 08:02:33 +00:00
|
|
|
if (N1N2MessageTransferReqData->is_skip_ind == true &&
|
|
|
|
N1N2MessageTransferReqData->skip_ind == true) {
|
2021-01-18 16:48:35 +00:00
|
|
|
N1N2MessageTransferRspData.cause =
|
|
|
|
OpenAPI_n1_n2_message_transfer_cause_N1_MSG_NOT_TRANSFERRED;
|
|
|
|
} else {
|
|
|
|
ogs_fatal("[%s] No skipInd", amf_ue->supi);
|
|
|
|
ogs_assert_if_reached();
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if (CM_CONNECTED(amf_ue)) {
|
|
|
|
ngapbuf = ngap_build_pdu_session_resource_release_command(
|
|
|
|
sess, NULL, n2buf);
|
|
|
|
ogs_assert(ngapbuf);
|
2020-07-31 02:10:20 +00:00
|
|
|
|
2021-01-18 16:48:35 +00:00
|
|
|
if (nas_5gs_send_to_gnb(amf_ue, ngapbuf) != OGS_OK)
|
|
|
|
ogs_error("nas_5gs_send_to_gnb() failed");
|
|
|
|
|
|
|
|
} else {
|
|
|
|
ogs_fatal("[%s] Invalid AMF-UE state", amf_ue->supi);
|
|
|
|
ogs_assert_if_reached();
|
2020-07-31 02:10:20 +00:00
|
|
|
}
|
2021-01-01 02:07:08 +00:00
|
|
|
break;
|
2020-06-17 05:22:28 +00:00
|
|
|
|
2021-01-01 02:07:08 +00:00
|
|
|
default:
|
2021-11-16 23:09:16 +00:00
|
|
|
ogs_error("Not implemented ngapIeType[%d]", ngapIeType);
|
2021-01-01 02:07:08 +00:00
|
|
|
ogs_assert_if_reached();
|
|
|
|
}
|
2020-06-17 05:22:28 +00:00
|
|
|
|
|
|
|
response = ogs_sbi_build_response(&sendmsg, status);
|
|
|
|
ogs_assert(response);
|
2021-06-06 13:35:46 +00:00
|
|
|
ogs_assert(true == ogs_sbi_server_send_response(stream, response));
|
2020-06-17 05:22:28 +00:00
|
|
|
|
2021-01-18 16:48:35 +00:00
|
|
|
if (sendmsg.http.location)
|
|
|
|
ogs_free(sendmsg.http.location);
|
|
|
|
|
2020-06-17 05:22:28 +00:00
|
|
|
return OGS_OK;
|
|
|
|
}
|
2020-07-02 05:50:23 +00:00
|
|
|
|
|
|
|
int amf_namf_callback_handle_sm_context_status(
|
2020-11-27 02:44:37 +00:00
|
|
|
ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg)
|
2020-07-02 05:50:23 +00:00
|
|
|
{
|
|
|
|
int status = OGS_SBI_HTTP_STATUS_NO_CONTENT;
|
|
|
|
|
|
|
|
amf_ue_t *amf_ue = NULL;
|
|
|
|
amf_sess_t *sess = NULL;
|
|
|
|
|
|
|
|
uint8_t pdu_session_identity;
|
|
|
|
|
|
|
|
ogs_sbi_message_t sendmsg;
|
|
|
|
ogs_sbi_response_t *response = NULL;
|
|
|
|
|
|
|
|
OpenAPI_sm_context_status_notification_t *SmContextStatusNotification;
|
|
|
|
OpenAPI_status_info_t *StatusInfo;
|
|
|
|
|
2020-11-27 02:44:37 +00:00
|
|
|
ogs_assert(stream);
|
2020-07-02 05:50:23 +00:00
|
|
|
ogs_assert(recvmsg);
|
|
|
|
|
|
|
|
if (!recvmsg->h.resource.component[0]) {
|
|
|
|
status = OGS_SBI_HTTP_STATUS_BAD_REQUEST;
|
|
|
|
ogs_error("No SUPI");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
amf_ue = amf_ue_find_by_supi(recvmsg->h.resource.component[0]);
|
|
|
|
if (!amf_ue) {
|
|
|
|
status = OGS_SBI_HTTP_STATUS_NOT_FOUND;
|
|
|
|
ogs_error("Cannot find SUPI [%s]", recvmsg->h.resource.component[0]);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!recvmsg->h.resource.component[2]) {
|
|
|
|
status = OGS_SBI_HTTP_STATUS_BAD_REQUEST;
|
|
|
|
ogs_error("[%s] No PDU Session Identity", amf_ue->supi);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
pdu_session_identity = atoi(recvmsg->h.resource.component[2]);
|
|
|
|
if (pdu_session_identity == OGS_NAS_PDU_SESSION_IDENTITY_UNASSIGNED) {
|
|
|
|
status = OGS_SBI_HTTP_STATUS_BAD_REQUEST;
|
|
|
|
ogs_error("[%s] PDU Session Identity is unassigned", amf_ue->supi);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
sess = amf_sess_find_by_psi(amf_ue, pdu_session_identity);
|
|
|
|
if (!sess) {
|
|
|
|
status = OGS_SBI_HTTP_STATUS_NOT_FOUND;
|
2020-07-04 03:14:48 +00:00
|
|
|
ogs_warn("[%s] Cannot find session", amf_ue->supi);
|
2020-07-02 05:50:23 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
SmContextStatusNotification = recvmsg->SmContextStatusNotification;
|
|
|
|
if (!SmContextStatusNotification) {
|
|
|
|
status = OGS_SBI_HTTP_STATUS_BAD_REQUEST;
|
2020-07-04 03:14:48 +00:00
|
|
|
ogs_error("[%s:%d] No SmContextStatusNotification",
|
|
|
|
amf_ue->supi, sess->psi);
|
2020-07-02 05:50:23 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
StatusInfo = SmContextStatusNotification->status_info;
|
|
|
|
if (!StatusInfo) {
|
|
|
|
status = OGS_SBI_HTTP_STATUS_BAD_REQUEST;
|
2020-07-04 03:14:48 +00:00
|
|
|
ogs_error("[%s:%d] No StatusInfo", amf_ue->supi, sess->psi);
|
2020-07-02 05:50:23 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2020-07-30 03:26:12 +00:00
|
|
|
sess->resource_status = StatusInfo->resource_status;
|
|
|
|
|
2020-08-03 03:22:41 +00:00
|
|
|
/*
|
|
|
|
* Race condition for PDU session release complete
|
|
|
|
* - CLIENT : /nsmf-pdusession/v1/sm-contexts/{smContextRef}/modify
|
|
|
|
* - SERVER : /namf-callback/v1/{supi}/sm-context-status/{psi})
|
|
|
|
*
|
|
|
|
* If NOTIFICATION is received before the CLIENT response is received,
|
|
|
|
* CLIENT sync is not finished. In this case, the session context
|
|
|
|
* should not be removed.
|
|
|
|
*
|
|
|
|
* If NOTIFICATION comes after the CLIENT response is received,
|
|
|
|
* sync is done. So, the session context can be removed.
|
|
|
|
*/
|
|
|
|
if (sess->n1_released == true &&
|
|
|
|
sess->n2_released == true &&
|
|
|
|
sess->resource_status == OpenAPI_resource_status_RELEASED) {
|
|
|
|
|
|
|
|
ogs_debug("[%s:%d] SM context remove", amf_ue->supi, sess->psi);
|
2021-01-28 19:23:54 +00:00
|
|
|
amf_nsmf_pdusession_handle_release_sm_context(
|
2021-02-04 04:49:16 +00:00
|
|
|
sess, AMF_RELEASE_SM_CONTEXT_NO_STATE);
|
2020-07-02 05:50:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
memset(&sendmsg, 0, sizeof(sendmsg));
|
|
|
|
|
|
|
|
response = ogs_sbi_build_response(&sendmsg, status);
|
|
|
|
ogs_assert(response);
|
2021-06-06 13:35:46 +00:00
|
|
|
ogs_assert(true == ogs_sbi_server_send_response(stream, response));
|
2020-07-02 05:50:23 +00:00
|
|
|
|
|
|
|
return OGS_OK;
|
|
|
|
}
|
2022-06-21 11:55:37 +00:00
|
|
|
|
|
|
|
int amf_namf_callback_handle_dereg_notify(
|
|
|
|
ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg)
|
|
|
|
{
|
|
|
|
int status = OGS_SBI_HTTP_STATUS_NO_CONTENT;
|
|
|
|
|
|
|
|
amf_ue_t *amf_ue = NULL;
|
|
|
|
|
|
|
|
ogs_sbi_message_t sendmsg;
|
|
|
|
ogs_sbi_response_t *response = NULL;
|
|
|
|
|
|
|
|
OpenAPI_deregistration_data_t *DeregistrationData;
|
|
|
|
|
|
|
|
ogs_assert(stream);
|
|
|
|
ogs_assert(recvmsg);
|
|
|
|
|
|
|
|
if (!recvmsg->h.resource.component[0]) {
|
|
|
|
status = OGS_SBI_HTTP_STATUS_BAD_REQUEST;
|
|
|
|
ogs_error("No SUPI");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
amf_ue = amf_ue_find_by_supi(recvmsg->h.resource.component[0]);
|
|
|
|
if (!amf_ue) {
|
|
|
|
status = OGS_SBI_HTTP_STATUS_NOT_FOUND;
|
|
|
|
ogs_error("Cannot find SUPI [%s]", recvmsg->h.resource.component[0]);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
DeregistrationData = recvmsg->DeregistrationData;
|
|
|
|
if (!DeregistrationData) {
|
|
|
|
status = OGS_SBI_HTTP_STATUS_BAD_REQUEST;
|
|
|
|
ogs_error("[%s] No DeregistrationData", amf_ue->supi);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (DeregistrationData->access_type != OpenAPI_access_type_3GPP_ACCESS)
|
|
|
|
{
|
|
|
|
status = OGS_SBI_HTTP_STATUS_BAD_REQUEST;
|
|
|
|
ogs_error("[%s] Deregistration access type not 3GPP", amf_ue->supi);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ogs_info("Deregistration notify reason: %s:%s:%s",
|
|
|
|
amf_ue->supi,
|
|
|
|
OpenAPI_deregistration_reason_ToString(DeregistrationData->dereg_reason),
|
|
|
|
OpenAPI_access_type_ToString(DeregistrationData->access_type));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* TODO: do not start deregistration if UE has emergency sessions
|
|
|
|
* 4.2.2.3.3
|
|
|
|
* If the UE has established PDU Session associated with emergency service, the AMF shall not initiate
|
|
|
|
* Deregistration procedure. In this case, the AMF performs network requested PDU Session Release for any PDU
|
|
|
|
* session associated with non-emergency service as described in clause 4.3.4.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
if (CM_CONNECTED(amf_ue))
|
|
|
|
{
|
|
|
|
amf_ue->network_initiated_de_reg = true;
|
|
|
|
|
|
|
|
ogs_assert(OGS_OK ==
|
|
|
|
nas_5gs_send_de_registration_request(amf_ue));
|
|
|
|
|
|
|
|
amf_sbi_send_release_all_sessions(
|
|
|
|
amf_ue, AMF_RELEASE_SM_CONTEXT_NO_STATE);
|
|
|
|
|
|
|
|
if (ogs_list_count(&amf_ue->sess_list) == 0)
|
|
|
|
ogs_assert(true ==
|
|
|
|
amf_ue_sbi_discover_and_send(
|
|
|
|
OpenAPI_nf_type_PCF, amf_ue,
|
|
|
|
NULL, amf_npcf_am_policy_control_build_delete));
|
|
|
|
|
|
|
|
OGS_FSM_TRAN(&amf_ue->sm, &gmm_state_de_registered);
|
|
|
|
}
|
|
|
|
else if (CM_IDLE(amf_ue)) {
|
|
|
|
/* TODO: need to page UE */
|
|
|
|
/*ngap_send_paging(amf_ue);*/
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
memset(&sendmsg, 0, sizeof(sendmsg));
|
|
|
|
|
|
|
|
response = ogs_sbi_build_response(&sendmsg, status);
|
|
|
|
ogs_assert(response);
|
|
|
|
ogs_assert(true == ogs_sbi_server_send_response(stream, response));
|
|
|
|
|
|
|
|
return OGS_OK;
|
|
|
|
}
|