Merge branch 'develop_SA_SIM' into develop_SA_L3

Conflicts:
	common/utils/ocp_itti/intertask_interface.h
	openair2/COMMON/gtpv1_u_messages_types.h
	openair2/GNB_APP/gnb_config.c
	openair2/RRC/NR/MESSAGES/asn1_msg.c
	openair2/RRC/NR/nr_rrc_proto.h
	openair2/RRC/NR/rrc_gNB.c
	openair2/RRC/NR/rrc_gNB_NGAP.c
	openair2/RRC/NR_UE/rrc_UE.c
	openair3/NAS/NR_UE/nr_nas_msg_sim.h
	openair3/NGAP/ngap_gNB_nas_procedures.c
This commit is contained in:
wu.jing
2020-11-24 09:15:52 +00:00
55 changed files with 3536 additions and 423 deletions
+341 -1
View File
@@ -38,6 +38,7 @@
#include "NwGtpv1uPrivate.h"
#include "NwLog.h"
#include "gtpv1u_eNB_defs.h"
#include "gtpv1u_gNB_defs.h"
#include "gtpv1_u_messages_types.h"
#include "udp_eNB_task.h"
#include "common/utils/LOG/log.h"
@@ -45,7 +46,6 @@
#include "COMMON/platform_constants.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
#include "common/ran_context.h"
#include "gtpv1u_eNB_defs.h"
#include "gtpv1u_eNB_task.h"
#include "gtpv1u_gNB_task.h"
#include "rrc_eNB_GTPV1U.h"
@@ -309,3 +309,343 @@ void *gtpv1u_gNB_task(void *args) {
return NULL;
}
int nr_gtpv1u_gNB_init(void) {
NwGtpv1uRcT rc = NW_GTPV1U_FAILURE;
NwGtpv1uUlpEntityT ulp;
NwGtpv1uUdpEntityT udp;
NwGtpv1uLogMgrEntityT log;
NwGtpv1uTimerMgrEntityT tmr;
// enb_properties_p = enb_config_get()->properties[0];
RC.nr_gtpv1u_data_g = (nr_gtpv1u_data_t *)calloc(sizeof(nr_gtpv1u_data_t),1);
LOG_I(GTPU, "Initializing GTPU stack %p\n",&RC.nr_gtpv1u_data_g);
/* Initialize UE hashtable */
RC.nr_gtpv1u_data_g->ue_mapping = hashtable_create (32, NULL, NULL);
AssertFatal(RC.nr_gtpv1u_data_g->ue_mapping != NULL, " ERROR Initializing TASK_GTPV1_U task interface: in hashtable_create returned %p\n", RC.gtpv1u_data_g->ue_mapping);
RC.nr_gtpv1u_data_g->teid_mapping = hashtable_create (256, NULL, NULL);
AssertFatal(RC.nr_gtpv1u_data_g->teid_mapping != NULL, " ERROR Initializing TASK_GTPV1_U task interface: in hashtable_create\n");
// RC.gtpv1u_data_g.enb_ip_address_for_S1u_S12_S4_up = enb_properties_p->enb_ipv4_address_for_S1U;
//gtpv1u_data_g.udp_data;
RC.nr_gtpv1u_data_g->seq_num = 0;
RC.nr_gtpv1u_data_g->restart_counter = 0;
/* Initializing GTPv1-U stack */
if ((rc = nwGtpv1uInitialize(&RC.nr_gtpv1u_data_g->gtpv1u_stack, GTPU_STACK_ENB)) != NW_GTPV1U_OK) {
LOG_E(GTPU, "Failed to setup nwGtpv1u stack %x\n", rc);
return -1;
}
if ((rc = nwGtpv1uSetLogLevel(RC.nr_gtpv1u_data_g->gtpv1u_stack,
NW_LOG_LEVEL_DEBG)) != NW_GTPV1U_OK) {
LOG_E(GTPU, "Failed to setup loglevel for stack %x\n", rc);
return -1;
}
/* Set the ULP API callback. Called once message have been processed by the
* nw-gtpv1u stack.
*/
ulp.ulpReqCallback = gtpv1u_gNB_process_stack_req;
memset((void *)&(ulp.hUlp), 0, sizeof(NwGtpv1uUlpHandleT));
if ((rc = nwGtpv1uSetUlpEntity(RC.nr_gtpv1u_data_g->gtpv1u_stack, &ulp)) != NW_GTPV1U_OK) {
LOG_E(GTPU, "nwGtpv1uSetUlpEntity: %x", rc);
return -1;
}
/* nw-gtpv1u stack requires an udp callback to send data over UDP.
* We provide a wrapper to UDP task.
*/
udp.udpDataReqCallback = gtpv1u_eNB_send_udp_msg;
memset((void *)&(udp.hUdp), 0, sizeof(NwGtpv1uUdpHandleT));
if ((rc = nwGtpv1uSetUdpEntity(RC.nr_gtpv1u_data_g->gtpv1u_stack, &udp)) != NW_GTPV1U_OK) {
LOG_E(GTPU, "nwGtpv1uSetUdpEntity: %x", rc);
return -1;
}
log.logReqCallback = gtpv1u_eNB_log_request;
memset((void *)&(log.logMgrHandle), 0, sizeof(NwGtpv1uLogMgrHandleT));
if ((rc = nwGtpv1uSetLogMgrEntity(RC.nr_gtpv1u_data_g->gtpv1u_stack, &log)) != NW_GTPV1U_OK) {
LOG_E(GTPU, "nwGtpv1uSetLogMgrEntity: %x", rc);
return -1;
}
/* Timer interface is more complicated as both wrappers doesn't send a message
* to the timer task but call the timer API functions start/stop timer.
*/
tmr.tmrMgrHandle = 0;
tmr.tmrStartCallback = gtpv1u_start_timer_wrapper;
tmr.tmrStopCallback = gtpv1u_stop_timer_wrapper;
if ((rc = nwGtpv1uSetTimerMgrEntity(RC.nr_gtpv1u_data_g->gtpv1u_stack, &tmr)) != NW_GTPV1U_OK) {
LOG_E(GTPU, "nwGtpv1uSetTimerMgrEntity: %x", rc);
return -1;
}
#if defined(GTP_DUMP_SOCKET) && GTP_DUMP_SOCKET > 0
if ((ret = gtpv1u_eNB_create_dump_socket()) < 0) {
return -1;
}
#endif
LOG_D(GTPU, "Initializing GTPV1U interface for eNB: DONE\n");
return 0;
}
//-----------------------------------------------------------------------------
int
gtpv1u_create_ngu_tunnel(
const instance_t instanceP,
const gtpv1u_gnb_create_tunnel_req_t *const create_tunnel_req_pP,
gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_pP)
{
/* Create a new nw-gtpv1-u stack req using API */
NwGtpv1uUlpApiT stack_req;
NwGtpv1uRcT rc = NW_GTPV1U_FAILURE;
/* Local tunnel end-point identifier */
teid_t ngu_teid = 0;
nr_gtpv1u_teid_data_t *gtpv1u_teid_data_p = NULL;
nr_gtpv1u_ue_data_t *gtpv1u_ue_data_p = NULL;
//MessageDef *message_p = NULL;
hashtable_rc_t hash_rc = HASH_TABLE_KEY_NOT_EXISTS;
int i;
pdusessionid_t pdusession_id = 0;
// int ipv4_addr = 0;
int ip_offset = 0;
in_addr_t in_addr;
int addrs_length_in_bytes= 0;
int loop_counter = 0;
int ret = 0;
MSC_LOG_RX_MESSAGE(
MSC_GTPU_GNB,
MSC_RRC_GNB,
NULL,0,
MSC_AS_TIME_FMT" CREATE_TUNNEL_REQ RNTI %"PRIx16" inst %u ntuns %u psid %u upf-ngu teid %u",
0,0,create_tunnel_req_pP->rnti, instanceP,
create_tunnel_req_pP->num_tunnels, create_tunnel_req_pP->pdusession_id[0],
create_tunnel_req_pP->upf_NGu_teid[0]);
create_tunnel_resp_pP->rnti = create_tunnel_req_pP->rnti;
create_tunnel_resp_pP->status = 0;
create_tunnel_resp_pP->num_tunnels = 0;
for (i = 0; i < create_tunnel_req_pP->num_tunnels; i++) {
ip_offset = 0;
loop_counter = 0;
pdusession_id = create_tunnel_req_pP->pdusession_id[i];
LOG_D(GTPU, "Rx GTPV1U_GNB_CREATE_TUNNEL_REQ ue rnti %x pdu session id %u\n",
create_tunnel_req_pP->rnti, pdusession_id);
memset(&stack_req, 0, sizeof(NwGtpv1uUlpApiT));
stack_req.apiType = NW_GTPV1U_ULP_API_CREATE_TUNNEL_ENDPOINT;
do {
ngu_teid = gtpv1u_new_teid();
LOG_D(GTPU, "gtpv1u_create_ngu_tunnel() 0x%x %u(dec)\n", ngu_teid, ngu_teid);
stack_req.apiInfo.createTunnelEndPointInfo.teid = ngu_teid;
stack_req.apiInfo.createTunnelEndPointInfo.hUlpSession = 0;
stack_req.apiInfo.createTunnelEndPointInfo.hStackSession = 0;
rc = nwGtpv1uProcessUlpReq(RC.nr_gtpv1u_data_g->gtpv1u_stack, &stack_req);
LOG_D(GTPU, ".\n");
loop_counter++;
} while (rc != NW_GTPV1U_OK && loop_counter < 10);
if ( rc != NW_GTPV1U_OK && loop_counter == 10 ) {
LOG_E(GTPU,"NwGtpv1uCreateTunnelEndPoint failed 10 times,start next loop\n");
ret = -1;
continue;
}
//-----------------------
// PDCP->GTPV1U mapping
//-----------------------
hash_rc = hashtable_get(RC.nr_gtpv1u_data_g->ue_mapping, create_tunnel_req_pP->rnti, (void **)&gtpv1u_ue_data_p);
if ((hash_rc == HASH_TABLE_KEY_NOT_EXISTS) || (hash_rc == HASH_TABLE_OK)) {
if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) {
gtpv1u_ue_data_p = calloc (1, sizeof(gtpv1u_ue_data_t));
hash_rc = hashtable_insert(RC.nr_gtpv1u_data_g->ue_mapping, create_tunnel_req_pP->rnti, gtpv1u_ue_data_p);
AssertFatal(hash_rc == HASH_TABLE_OK, "Error inserting ue_mapping in GTPV1U hashtable");
}
gtpv1u_ue_data_p->ue_id = create_tunnel_req_pP->rnti;
gtpv1u_ue_data_p->instance_id = 0; // TO DO
memcpy(&create_tunnel_resp_pP->gnb_addr.buffer,
&RC.nr_gtpv1u_data_g->gnb_ip_address_for_NGu_up,
sizeof (in_addr_t));
LOG_I(GTPU,"Configured GTPu address : %x\n",RC.nr_gtpv1u_data_g->gnb_ip_address_for_NGu_up);
create_tunnel_resp_pP->gnb_addr.length = sizeof (in_addr_t);
addrs_length_in_bytes = create_tunnel_req_pP->upf_addr[i].length / 8;
AssertFatal((addrs_length_in_bytes == 4) ||
(addrs_length_in_bytes == 16) ||
(addrs_length_in_bytes == 20),
"Bad transport layer address length %d (bits) %d (bytes)",
create_tunnel_req_pP->upf_addr[i].length, addrs_length_in_bytes);
if ((addrs_length_in_bytes == 4) ||
(addrs_length_in_bytes == 20)) {
in_addr = *((in_addr_t *)create_tunnel_req_pP->upf_addr[i].buffer);
ip_offset = 4;
gtpv1u_ue_data_p->bearers[pdusession_id - GTPV1U_BEARER_OFFSET].upf_ip_addr = in_addr;
}
if ((addrs_length_in_bytes == 16) ||
(addrs_length_in_bytes == 20)) {
memcpy(gtpv1u_ue_data_p->bearers[pdusession_id - GTPV1U_BEARER_OFFSET].upf_ip6_addr.s6_addr,
&create_tunnel_req_pP->upf_addr[i].buffer[ip_offset],
16);
}
gtpv1u_ue_data_p->bearers[pdusession_id - GTPV1U_BEARER_OFFSET].state = BEARER_IN_CONFIG;
gtpv1u_ue_data_p->bearers[pdusession_id - GTPV1U_BEARER_OFFSET].teid_gNB = ngu_teid;
gtpv1u_ue_data_p->bearers[pdusession_id - GTPV1U_BEARER_OFFSET].teid_gNB_stack_session = stack_req.apiInfo.createTunnelEndPointInfo.hStackSession;
gtpv1u_ue_data_p->bearers[pdusession_id - GTPV1U_BEARER_OFFSET].teid_upf = create_tunnel_req_pP->upf_NGu_teid[i];
gtpv1u_ue_data_p->num_bearers++;
create_tunnel_resp_pP->gnb_NGu_teid[i] = ngu_teid;
LOG_I(GTPU,"Copied to create_tunnel_resp tunnel: index %d target gNB ip %d.%d.%d.%d length %d gtp teid %u\n",
i,
create_tunnel_resp_pP->gnb_addr.buffer[0],
create_tunnel_resp_pP->gnb_addr.buffer[1],
create_tunnel_resp_pP->gnb_addr.buffer[2],
create_tunnel_resp_pP->gnb_addr.buffer[3],
create_tunnel_resp_pP->gnb_addr.length,
create_tunnel_resp_pP->gnb_NGu_teid[i]);
} else {
create_tunnel_resp_pP->gnb_NGu_teid[i] = 0;
create_tunnel_resp_pP->status = 0xFF;
}
create_tunnel_resp_pP->pdusession_id[i] = pdusession_id;
create_tunnel_resp_pP->num_tunnels += 1;
//-----------------------
// GTPV1U->PDCP mapping
//-----------------------
hash_rc = hashtable_get(RC.nr_gtpv1u_data_g->teid_mapping, ngu_teid, (void **)&gtpv1u_teid_data_p);
if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) {
gtpv1u_teid_data_p = calloc (1, sizeof(nr_gtpv1u_teid_data_t));
gtpv1u_teid_data_p->gnb_id = 0; // TO DO
gtpv1u_teid_data_p->ue_id = create_tunnel_req_pP->rnti;
gtpv1u_teid_data_p->pdu_session_id = pdusession_id;
hash_rc = hashtable_insert(RC.nr_gtpv1u_data_g->teid_mapping, ngu_teid, gtpv1u_teid_data_p);
AssertFatal(hash_rc == HASH_TABLE_OK, "Error inserting teid mapping in GTPV1U hashtable");
} else {
create_tunnel_resp_pP->gnb_NGu_teid[i] = 0;
create_tunnel_resp_pP->status = 0xFF;
}
}
MSC_LOG_TX_MESSAGE(
MSC_GTPU_GNB,
MSC_RRC_GNB,
NULL,0,
"0 GTPV1U_GNB_CREATE_TUNNEL_RESP rnti %x teid %x",
create_tunnel_resp_pP->rnti,
ngu_teid);
LOG_D(GTPU, "Tx GTPV1U_GNB_CREATE_TUNNEL_RESP ue rnti %x status %d\n",
create_tunnel_req_pP->rnti,
create_tunnel_resp_pP->status);
//return 0;
return ret;
}
//-----------------------------------------------------------------------------
static int gtpv1u_gNB_send_init_udp(const Gtpv1uNGReq *req) {
// Create and alloc new message
MessageDef *message_p;
struct in_addr addr= {0};
message_p = itti_alloc_new_message(TASK_GTPV1_U, UDP_INIT);
if (message_p == NULL) {
return -1;
}
UDP_INIT(message_p).port = req->gnb_port_for_NGu_up;
addr.s_addr = req->gnb_ip_address_for_NGu_up;
UDP_INIT(message_p).address = inet_ntoa(addr);
LOG_I(GTPU, "Tx UDP_INIT IP addr %s (%x)\n", UDP_INIT(message_p).address,UDP_INIT(message_p).port);
MSC_LOG_EVENT(
MSC_GTPU_ENB,
"0 UDP bind %s:%u",
UDP_INIT(message_p).address,
UDP_INIT(message_p).port);
return itti_send_msg_to_task(TASK_UDP, INSTANCE_DEFAULT, message_p);
}
static int gtpv1u_ng_req(
const instance_t instanceP,
const Gtpv1uNGReq *const req) {
memcpy(&RC.nr_gtpv1u_data_g->gnb_ip_address_for_NGu_up,
&req->gnb_ip_address_for_NGu_up,
sizeof (req->gnb_ip_address_for_NGu_up));
gtpv1u_gNB_send_init_udp(req);
return 0;
}
//-----------------------------------------------------------------------------
void *gtpv1u_gNB_process_itti_msg(void *notUsed) {
/* Trying to fetch a message from the message queue.
* If the queue is empty, this function will block till a
* message is sent to the task.
*/
instance_t instance;
MessageDef *received_message_p = NULL;
int rc = 0;
itti_receive_msg(TASK_GTPV1_U, &received_message_p);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_ENB_TASK, VCD_FUNCTION_IN);
DevAssert(received_message_p != NULL);
instance = ITTI_MSG_INSTANCE(received_message_p);
switch (ITTI_MSG_ID(received_message_p)) {
case GTPV1U_GNB_NG_REQ:
gtpv1u_ng_req(instance, &received_message_p->ittiMsg.gtpv1uNGReq);
break;
case TERMINATE_MESSAGE: {
if (RC.nr_gtpv1u_data_g->ue_mapping != NULL) {
hashtable_destroy (&(RC.nr_gtpv1u_data_g->ue_mapping));
}
if (RC.nr_gtpv1u_data_g->teid_mapping != NULL) {
hashtable_destroy (&(RC.nr_gtpv1u_data_g->teid_mapping));
}
LOG_W(GTPU, " *** Exiting GTPU thread\n");
itti_exit_task();
}
break;
case TIMER_HAS_EXPIRED:
nwGtpv1uProcessTimeout(&received_message_p->ittiMsg.timer_has_expired.arg);
break;
default: {
LOG_E(GTPU, "Unkwnon message ID %d:%s\n",
ITTI_MSG_ID(received_message_p),
ITTI_MSG_NAME(received_message_p));
}
break;
}
rc = itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), received_message_p);
AssertFatal(rc == EXIT_SUCCESS, "Failed to free memory (%d)!\n", rc);
received_message_p = NULL;
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_ENB_TASK, VCD_FUNCTION_OUT);
return NULL;
}
void *nr_gtpv1u_gNB_task(void *args) {
int rc = 0;
rc = nr_gtpv1u_gNB_init();
AssertFatal(rc == 0, "gtpv1u_gNB_init Failed");
itti_mark_task_ready(TASK_GTPV1_U);
MSC_START_USE();
while(1) {
(void) gtpv1u_gNB_process_itti_msg (NULL);
}
return NULL;
}
+116
View File
@@ -0,0 +1,116 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file gtpv1u_gNB_defs.h
* \brief
* \author Yoshio INOUE, Masayuki HARADA
* \date 2020
* \version 0.1
* \email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com
* (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com)
*/
#include "hashtable.h"
#include "NR_asn_constant.h"
#ifndef GTPV1U_GNB_DEFS_H_
#define GTPV1U_GNB_DEFS_H_
#include "NwGtpv1u.h"
#define GTPV1U_UDP_PORT (2152)
#define NR_GTPV1U_MAX_BEARERS_ID (max_val_NR_DRB_Identity - 3)
#define GTPV1U_SOURCE_GNB (0)
#define GTPV1U_TARGET_GNB (1)
#define GTPV1U_MSG_FROM_SOURCE_GNB (0)
#define GTPV1U_MSG_FROM_UPF (1)
typedef struct nr_gtpv1u_teid_data_s {
/* UE identifier for oaisim stack */
module_id_t gnb_id;
rnti_t ue_id;
pdusessionid_t pdu_session_id;
} nr_gtpv1u_teid_data_t;
typedef struct nr_gtpv1u_bearer_s {
/* TEID used in dl and ul */
teid_t teid_gNB; ///< gNB TEID
uintptr_t teid_gNB_stack_session; ///< gNB TEID
teid_t teid_upf; ///< Remote TEID
in_addr_t upf_ip_addr;
struct in6_addr upf_ip6_addr;
teid_t teid_tgNB;
in_addr_t tgnb_ip_addr; ///< target gNB ipv4
struct in6_addr tgnb_ip6_addr; ///< target gNB ipv6
tcp_udp_port_t port;
//NwGtpv1uStackSessionHandleT stack_session;
bearer_state_t state;
} nr_gtpv1u_bearer_t;
typedef struct nr_gtpv1u_ue_data_s {
/* UE identifier for oaisim stack */
rnti_t ue_id;
/* Unique identifier used between PDCP and GTP-U to distinguish UEs */
uint32_t instance_id;
int num_bearers;
/* Bearer related data.
* Note that the first LCID available for data is 3 and we fixed the maximum
* number of e-rab per UE to be (32 [id range]), max RB is 11. The real rb id will 3 + rab_id (3..32).
*/
nr_gtpv1u_bearer_t bearers[NR_GTPV1U_MAX_BEARERS_ID];
//RB_ENTRY(gtpv1u_ue_data_s) gtpv1u_ue_node;
} nr_gtpv1u_ue_data_t;
typedef struct nr_gtpv1u_data_s {
/* nwgtpv1u stack internal data */
NwGtpv1uStackHandleT gtpv1u_stack;
/* RB tree of UEs */
hash_table_t *ue_mapping; // PDCP->GTPV1U
hash_table_t *teid_mapping; // GTPV1U -> PDCP
//RB_HEAD(gtpv1u_ue_map, gtpv1u_ue_data_s) gtpv1u_ue_map_head;
/* Local IP address to use */
in_addr_t gnb_ip_address_for_NGu_up;
/* UDP internal data */
//udp_data_t udp_data;
uint16_t seq_num;
uint8_t restart_counter;
#ifdef GTPU_IN_KERNEL
char *interface_name;
int interface_index;
struct iovec *malloc_ring;
void *sock_mmap_ring[16];
int sock_desc[16]; // indexed by marking
#endif
} nr_gtpv1u_data_t;
#endif /* GTPV1U_GNB_DEFS_H_ */
+7
View File
@@ -32,6 +32,13 @@ int gtpv1u_gNB_init(void);
void *gtpv1u_gNB_task(void *args);
void *nr_gtpv1u_gNB_task(void *args);
int
gtpv1u_create_ngu_tunnel(
const instance_t instanceP,
const gtpv1u_gnb_create_tunnel_req_t * const create_tunnel_req_pP,
gtpv1u_gnb_create_tunnel_resp_t * const create_tunnel_resp_pP);
#endif /* GTPV1U_GNB_TASK_H_ */
@@ -0,0 +1,35 @@
/*! \file FGSAuthenticationResponse.c
\brief authentication response procedures
\author Yoshio INOUE, Masayuki HARADA
\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com
\date 2020
\version 0.1
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "nas_log.h"
#include "FGSAuthenticationResponse.h"
int encode_fgs_authentication_response(fgs_authentication_response_msg *authentication_response, uint8_t *buffer, uint32_t len)
{
int encoded = 0;
int encode_result = 0;
if ((encode_result =
encode_authentication_response_parameter(&authentication_response->authenticationresponseparameter,
AUTHENTICATION_RESPONSE_PARAMETER_IEI, buffer + encoded, len - encoded)) < 0) //Return in case of error
return encode_result;
else
encoded += encode_result;
return encoded;
}
@@ -0,0 +1,45 @@
/*! \file FGSAuthenticationResponse.h
\brief authentication response procedures
\author Yoshio INOUE, Masayuki HARADA
\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com
\date 2020
\version 0.1
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "ExtendedProtocolDiscriminator.h"
#include "SecurityHeaderType.h"
#include "SpareHalfOctet.h"
#include "MessageType.h"
#include "AuthenticationResponseParameter.h"
#ifndef FGS_AUTHENTICATION_RESPONSE_H_
#define FGS_AUTHENTICATION_RESPONSE_H_
#define AUTHENTICATION_RESPONSE_PARAMETER_IEI 0x2d
/*
* Message name: Identity response
* Description: This message is sent by the UE to the AMF to provide the requested identity. See table 8.2.22.1.
* Significance: dual
* Direction: UE to AMF
*/
typedef struct fgs_authentication_response_msg_tag {
/* Mandatory fields */
ExtendedProtocolDiscriminator protocoldiscriminator;
SecurityHeaderType securityheadertype:4;
SpareHalfOctet sparehalfoctet:4;
MessageType messagetype;
AuthenticationResponseParameter authenticationresponseparameter;
} fgs_authentication_response_msg;
int encode_fgs_authentication_response(fgs_authentication_response_msg *authentication_response, uint8_t *buffer, uint32_t len);
#endif /* ! defined(FGS_AUTHENTICATION_RESPONSE_H_) */
@@ -0,0 +1,35 @@
/*! \file FGSIdentityResponse.c
\brief identity response procedures for gNB
\author Yoshio INOUE, Masayuki HARADA
\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com
\date 2020
\version 0.1
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "nas_log.h"
#include "FGSIdentityResponse.h"
int encode_identiy_response(fgs_identiy_response_msg *fgs_identity_reps, uint8_t *buffer, uint32_t len)
{
int encoded = 0;
int encode_result = 0;
if ((encode_result =
encode_5gs_mobile_identity(&fgs_identity_reps->fgsmobileidentity, 0, buffer +
encoded, len - encoded)) < 0) //Return in case of error
return encode_result;
else
encoded += encode_result;
return encoded;
}
@@ -0,0 +1,44 @@
/*! \file FGSIdentityResponse.h
\brief identity response procedures for gNB
\author Yoshio INOUE, Masayuki HARADA
\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com
\date 2020
\version 0.1
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "ExtendedProtocolDiscriminator.h"
#include "SecurityHeaderType.h"
#include "SpareHalfOctet.h"
#include "FGSMobileIdentity.h"
#include "MessageType.h"
#ifndef FGS_IDENTITY_RESPONSE_H_
#define FGS_IDENTITY_RESPONSE_H_
/*
* Message name: Identity response
* Description: This message is sent by the UE to the AMF to provide the requested identity. See table 8.2.22.1.
* Significance: dual
* Direction: UE to AMF
*/
typedef struct fgs_identiy_response_msg_tag {
/* Mandatory fields */
ExtendedProtocolDiscriminator protocoldiscriminator;
SecurityHeaderType securityheadertype:4;
SpareHalfOctet sparehalfoctet:4;
MessageType messagetype;
FGSMobileIdentity fgsmobileidentity;
} fgs_identiy_response_msg;
int encode_identiy_response(fgs_identiy_response_msg *fgs_identity_reps, uint8_t *buffer, uint32_t len);
#endif /* ! defined(FGS_IDENTITY_RESPONSE_H_) */
@@ -0,0 +1,45 @@
/*! \file FGSNASSecurityModeComplete.c
\brief security mode complete procedures for gNB
\author Yoshio INOUE, Masayuki HARADA
\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com
\date 2020
\version 0.1
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "nas_log.h"
#include "FGSNASSecurityModeComplete.h"
#include "FGSMobileIdentity.h"
#include "FGCNasMessageContainer.h"
int encode_fgs_security_mode_complete(fgs_security_mode_complete_msg *fgs_security_mode_comp, uint8_t *buffer, uint32_t len)
{
int encoded = 0;
int encode_result = 0;
if ((encode_result =
encode_5gs_mobile_identity(&fgs_security_mode_comp->fgsmobileidentity, 0x77, buffer +
encoded, len - encoded)) < 0) { //Return in case of error
return encode_result;
} else {
encoded += encode_result;
if ((encode_result =
encode_fgc_nas_message_container(&fgs_security_mode_comp->fgsnasmessagecontainer, 0x71, buffer +
encoded, len - encoded)) < 0) {
return encode_result;
} else {
encoded += encode_result;
}
}
return encoded;
}
@@ -0,0 +1,44 @@
/*! \file FGSNASSecurityModeComplete.h
\brief security mode complete procedures for gNB
\author Yoshio INOUE, Masayuki HARADA
\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com
\date 2020
\version 0.1
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "ExtendedProtocolDiscriminator.h"
#include "SecurityHeaderType.h"
#include "SpareHalfOctet.h"
#include "FGSMobileIdentity.h"
#include "MessageType.h"
#include "FGCNasMessageContainer.h"
#ifndef FGS_NAS_SECURITY_MODE_COMPLETE_H_
#define FGS_NAS_SECURITY_MODE_COMPLETE_H_
/*
* Message name: security mode complete
* Description: This message is sent by the UE to the AMF in response to a SECURITY MODE COMMAND message. See table 8.2.26.1.1.
* Significance: dual
* Direction: UE to AMF
*/
typedef struct fgs_security_mode_complete_msg_tag {
/* Mandatory fields */
ExtendedProtocolDiscriminator protocoldiscriminator;
SecurityHeaderType securityheadertype:4;
SpareHalfOctet sparehalfoctet:4;
MessageType messagetype;
FGSMobileIdentity fgsmobileidentity;
FGCNasMessageContainer fgsnasmessagecontainer;
} fgs_security_mode_complete_msg;
int encode_fgs_security_mode_complete(fgs_security_mode_complete_msg *fgs_security_mode_comp, uint8_t *buffer, uint32_t len);
#endif /* ! defined(FGS_NAS_SECURITY_MODE_COMPLETE_H_) */
@@ -0,0 +1,129 @@
/*! \file FGSUplinkNasTransport.c
\brief uplink nas transport procedures
\author Yoshio INOUE, Masayuki HARADA
\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com
\date 2020
\version 0.1
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <arpa/inet.h>
#include "FGSUplinkNasTransport.h"
#include "TLVEncoder.h"
int encode_fgs_payload_container(FGSPayloadContainer *paycontainer, uint8_t iei, uint8_t *buffer, uint32_t len)
{
uint32_t encoded = 0;
int encode_result;
if (iei > 0) {
*buffer = iei;
encoded++;
}
encoded += 2;
if ((encode_result = encode_octet_string(&paycontainer->payloadcontainercontents, buffer + encoded, len - encoded)) < 0) {
return encode_result;
} else {
encoded += encode_result;
}
if(iei > 0){
*(uint16_t*) (buffer+1) = htons(encoded - 3);
} else {
*(uint16_t*) (buffer) = htons(encoded - 2);
}
return encoded;
}
int encode_nssai(OctetString *nssai, uint8_t iei, uint8_t *buffer)
{
uint32_t encoded = 0;
int encode_result;
if (iei > 0) {
*buffer = iei;
encoded++;
}
*(buffer + encoded) = nssai->length;
encoded++;
if ((encode_result = encode_octet_string(nssai, buffer + encoded, nssai->length)) < 0) {
return encode_result;
} else {
encoded += encode_result;
}
return encoded;
}
int encode_dnn(OctetString *dnn, uint8_t iei, uint8_t *buffer)
{
uint32_t encoded = 0;
int encode_result;
if (iei > 0) {
*buffer = iei;
encoded++;
}
*(buffer + encoded) = dnn->length;
encoded++;
if ((encode_result = encode_octet_string(dnn, buffer + encoded, dnn->length)) < 0) {
return encode_result;
} else {
encoded += encode_result;
}
return encoded;
}
int encode_fgs_uplink_nas_transport(fgs_uplink_nas_transport_msg *fgs_up_nas_transport, uint8_t *buffer, uint32_t len)
{
int encoded = 0;
int encode_result = 0;
*(buffer + encoded) = (fgs_up_nas_transport->payloadcontainertype.iei << 4) | (fgs_up_nas_transport->payloadcontainertype.type &0xf);
encoded++;
if ((encode_result = encode_fgs_payload_container(&fgs_up_nas_transport->fgspayloadcontainer,
0, buffer +encoded, len - encoded)) < 0) {
return encode_result;
} else {
encoded += encode_result;
}
*(buffer + encoded) = 0x12;
encoded++;
IES_ENCODE_U8(buffer, encoded, fgs_up_nas_transport->pdusessionid);
// set request type
*(buffer + encoded) = (0x8<<4)|(fgs_up_nas_transport->requesttype &0x7);
encoded++;
if ((encode_result = encode_nssai(&fgs_up_nas_transport->snssai, 0x22, buffer +encoded)) < 0) {
return encode_result;
} else {
encoded += encode_result;
}
if ((encode_result = encode_dnn(&fgs_up_nas_transport->dnn, 0x25, buffer +encoded)) < 0) {
return encode_result;
} else {
encoded += encode_result;
}
return encoded;
}
@@ -0,0 +1,56 @@
/*! \file FGSUplinkNasTransport.h
\brief uplink nas transport procedures
\author Yoshio INOUE, Masayuki HARADA
\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com
\date 2020
\version 0.1
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "ExtendedProtocolDiscriminator.h"
#include "SecurityHeaderType.h"
#include "SpareHalfOctet.h"
#include "MessageType.h"
#ifndef FGS_UPLINK_NAS_TRANSPORT_H_
#define FGS_UPLINK_NAS_TRANSPORT_H_
/*
* Message name: uplink nas transpaort
* Description: The UL NAS TRANSPORT message transports message payload and associated information to the AMF. See table 8.2.10.1.1.
* Significance: dual
* Direction: UE to network
*/
typedef struct PayloadContainerType_tag{
uint8_t iei:4;
uint8_t type:4;
}PayloadContainerType;
typedef struct FGSPayloadContainer_tag {
OctetString payloadcontainercontents;
} FGSPayloadContainer;
typedef struct fgs_uplink_nas_transport_msg_tag {
/* Mandatory fields */
ExtendedProtocolDiscriminator protocoldiscriminator;
SecurityHeaderType securityheadertype:4;
SpareHalfOctet sparehalfoctet:4;
MessageType messagetype;
PayloadContainerType payloadcontainertype;
FGSPayloadContainer fgspayloadcontainer;
/* Optional fields */
uint16_t pdusessionid;
uint8_t requesttype;
OctetString snssai;
OctetString dnn;
} fgs_uplink_nas_transport_msg;
int encode_fgs_uplink_nas_transport(fgs_uplink_nas_transport_msg *fgs_security_mode_comp, uint8_t *buffer, uint32_t len);
#endif /* ! defined(FGS_UPLINK_NAS_TRANSPORT_H_) */
@@ -0,0 +1,49 @@
/*! \file RegistrationAccept.c
\brief 5GS registration accept procedures
\author Yoshio INOUE, Masayuki HARADA
\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com
\date 2020
\version 0.1
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "TLVEncoder.h"
#include "TLVDecoder.h"
#include "RegistrationAccept.h"
#include "assertions.h"
int decode_registration_accept(registration_accept_msg *registration_accept, uint8_t *buffer, uint32_t len)
{
uint32_t decoded = 0;
int decoded_result = 0;
/* Decoding mandatory fields */
if ((decoded_result = decode_fgs_registration_result(&registration_accept->fgsregistrationresult, 0, *(buffer + decoded), len - decoded)) < 0)
return decoded_result;
decoded += decoded_result;
// todo ,Decoding optional fields
return decoded;
}
int encode_registration_accept(registration_accept_msg *registration_accept, uint8_t *buffer, uint32_t len)
{
int encoded = 0;
LOG_FUNC_IN;
*(buffer + encoded) = encode_fgs_registration_result(&registration_accept->fgsregistrationresult);
encoded = encoded + 2;
// todo ,Encoding optional fields
LOG_FUNC_RETURN(encoded);
}
@@ -0,0 +1,45 @@
/*! \file RegistrationAccept.h
\brief 5GS registration accept procedures
\author Yoshio INOUE, Masayuki HARADA
\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com
\date 2020
\version 0.1
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "ExtendedProtocolDiscriminator.h"
#include "SecurityHeaderType.h"
#include "SpareHalfOctet.h"
#include "MessageType.h"
#include "FGSRegistrationResult.h"
#ifndef REGISTRATION_ACCEPT_H_
#define REGISTRATION_ACCEPT_H_
/*
* Message name: Registration accept
* Description: The REGISTRATION ACCEPT message is sent by the AMF to the UE. See table 8.2.7.1.1.
* Significance: dual
* Direction: network to UE
*/
typedef struct registration_accept_msg_tag {
/* Mandatory fields */
ExtendedProtocolDiscriminator protocoldiscriminator;
SecurityHeaderType securityheadertype:4;
SpareHalfOctet sparehalfoctet:4;
MessageType messagetype;
FGSRegistrationResult fgsregistrationresult;
} registration_accept_msg;
int decode_registration_accept(registration_accept_msg *registrationaccept, uint8_t *buffer, uint32_t len);
int encode_registration_accept(registration_accept_msg *registrationaccept, uint8_t *buffer, uint32_t len);
#endif /* ! defined(REGISTRATION_ACCEPT_H_) */
@@ -0,0 +1,40 @@
/*! \file PduSessionEstablishRequest.c
\brief pdu session establishment request procedures
\author Yoshio INOUE, Masayuki HARADA
\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com
\date 2020
\version 0.1
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "TLVEncoder.h"
#include "TLVDecoder.h"
#include "PduSessionEstablishRequest.h"
int encode_pdu_session_establishment_request(pdu_session_establishment_request_msg *pdusessionestablishrequest, uint8_t *buffer)
{
int encoded = 0;
*(buffer + encoded) = pdusessionestablishrequest->protocoldiscriminator;
encoded++;
*(buffer + encoded) = pdusessionestablishrequest->pdusessionid;
encoded++;
*(buffer + encoded) = pdusessionestablishrequest->pti;
encoded++;
*(buffer + encoded) = pdusessionestablishrequest->pdusessionestblishmsgtype;
encoded++;
IES_ENCODE_U16(buffer, encoded, pdusessionestablishrequest->maxdatarate);
return encoded;
}
@@ -0,0 +1,43 @@
/*! \file PduSessionEstablishRequest.h
\brief pdu session establishment request procedures
\author Yoshio INOUE, Masayuki HARADA
\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com
\date 2020
\version 0.1
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "ExtendedProtocolDiscriminator.h"
#include "MessageType.h"
#ifndef PDU_SESSION_ESTABLISHMENT_REQUEST_H_
#define PDU_SESSION_ESTABLISHMENT_REQUEST_H_
/*
* Message name: pdu session establishment request
* Description: The PDU SESSION ESTABLISHMENT REQUEST message is sent by the UE to the SMF to initiate establishment of a PDU session. See table 8.3.1.1.1.
* Significance: dual
* Direction: UE to network
*/
typedef struct pdu_session_establishment_request_msg_tag {
/* Mandatory fields */
ExtendedProtocolDiscriminator protocoldiscriminator;
uint8_t pdusessionid;
uint8_t pti;
MessageType pdusessionestblishmsgtype;
uint16_t maxdatarate;
/* Optional fields */
} pdu_session_establishment_request_msg;
int encode_pdu_session_establishment_request(pdu_session_establishment_request_msg *pdusessionestablishrequest, uint8_t *buffer);
#endif /* ! defined(PDU_SESSION_ESTABLISHMENT_REQUEST_H_) */
@@ -0,0 +1,77 @@
/*! \file FGCNasMessageContainer.c
\brief security mode complete procedures for gNB
\author Yoshio INOUE, Masayuki HARADA
\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com
\date 2020
\version 0.1
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "TLVEncoder.h"
#include "TLVDecoder.h"
#include "FGCNasMessageContainer.h"
int decode_fgc_nas_message_container(FGCNasMessageContainer *nasmessagecontainer, uint8_t iei, uint8_t *buffer, uint32_t len)
{
int decoded = 0;
uint8_t ielen = 0;
int decode_result;
if (iei > 0) {
CHECK_IEI_DECODER(iei, *buffer);
decoded++;
}
ielen = *(buffer + decoded);
decoded += 2;
CHECK_LENGTH_DECODER(len - decoded, ielen);
if ((decode_result = decode_octet_string(&nasmessagecontainer->nasmessagecontainercontents, ielen, buffer + decoded, len - decoded)) < 0)
return decode_result;
else
decoded += decode_result;
return decoded;
}
int encode_fgc_nas_message_container(FGCNasMessageContainer *nasmessagecontainer, uint8_t iei, uint8_t *buffer, uint32_t len)
{
uint32_t encoded = 0;
int encode_result;
/* Checking IEI and pointer */
CHECK_PDU_POINTER_AND_LENGTH_ENCODER(buffer, FGC_NAS_MESSAGE_CONTAINER_MINIMUM_LENGTH, len);
if (iei > 0) {
*buffer = iei;
encoded++;
}
encoded += 2;
if ((encode_result = encode_octet_string(&nasmessagecontainer->nasmessagecontainercontents, buffer + encoded, len - encoded)) < 0) {
return encode_result;
} else {
*(uint16_t*) (buffer+1) = htons(encoded + encode_result - 3);
encoded += encode_result;
}
return encoded;
}
void dump_fgc_nas_message_container_xml(FGCNasMessageContainer *nasmessagecontainer, uint8_t iei)
{
printf("<Nas Message Container>\n");
if (iei > 0)
/* Don't display IEI if = 0 */
printf(" <IEI>0x%X</IEI>\n", iei);
printf("%s", dump_octet_string_xml(&nasmessagecontainer->nasmessagecontainercontents));
printf("</Nas Message Container>\n");
}
@@ -0,0 +1,33 @@
/*! \file FGCNasMessageContainer.h
\brief security mode complete procedures for gNB
\author Yoshio INOUE, Masayuki HARADA
\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com
\date 2020
\version 0.1
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "OctetString.h"
#ifndef FGC_NAS_MESSAGE_CONTAINER_H_
#define FGC_NAS_MESSAGE_CONTAINER_H_
#define FGC_NAS_MESSAGE_CONTAINER_MINIMUM_LENGTH 4
#define FGC_NAS_MESSAGE_CONTAINER_MAXIMUM_LENGTH 65535
typedef struct FGCNasMessageContainer_tag {
OctetString nasmessagecontainercontents;
} FGCNasMessageContainer;
int encode_fgc_nas_message_container(FGCNasMessageContainer *nasmessagecontainer, uint8_t iei, uint8_t *buffer, uint32_t len);
int decode_fgc_nas_message_container(FGCNasMessageContainer *nasmessagecontainer, uint8_t iei, uint8_t *buffer, uint32_t len);
void dump_fgc_nas_message_container_xml(FGCNasMessageContainer *nasmessagecontainer, uint8_t iei);
#endif /* FGC NAS MESSAGE CONTAINER_H_ */
+66 -2
View File
@@ -40,6 +40,8 @@
static int decode_guti_5gs_mobile_identity(Guti5GSMobileIdentity_t *guti, uint8_t *buffer);
static int encode_guti_5gs_mobile_identity(Guti5GSMobileIdentity_t *guti, uint8_t *buffer);
static int encode_suci_5gs_mobile_identity(Suci5GSMobileIdentity_t *suci, uint8_t *buffer);
static int encode_imeisv_5gs_mobile_identity(Imeisv5GSMobileIdentity_t *imeisv, uint8_t *buffer);
int decode_5gs_mobile_identity(FGSMobileIdentity *fgsmobileidentity, uint8_t iei, uint8_t *buffer, uint32_t len)
{
@@ -87,11 +89,26 @@ int encode_5gs_mobile_identity(FGSMobileIdentity *fgsmobileidentity, uint8_t iei
buffer + encoded);
}
if (fgsmobileidentity->suci.typeofidentity == FGS_MOBILE_IDENTITY_SUCI) {
encoded_rc = encode_suci_5gs_mobile_identity(&fgsmobileidentity->suci,
buffer + encoded);
}
if (fgsmobileidentity->imeisv.typeofidentity == FGS_MOBILE_IDENTITY_IMEISV) {
encoded_rc = encode_imeisv_5gs_mobile_identity(&fgsmobileidentity->imeisv,
buffer + encoded);
}
if (encoded_rc < 0) {
return encoded_rc;
}
*(uint16_t*) buffer = htons(encoded + encoded_rc - 2 - ((iei > 0) ? 1 : 0));
if(iei > 0){
*(uint16_t*) (buffer+1) = htons(encoded + encoded_rc - 3);
} else {
*(uint16_t*) buffer = htons(encoded + encoded_rc - 2);
}
return (encoded + encoded_rc);
}
@@ -166,10 +183,57 @@ static int encode_guti_5gs_mobile_identity(Guti5GSMobileIdentity_t *guti, uint8_
*(buffer + encoded) = guti->amfregionid;
encoded++;
temp = 0x00 | ((guti->amfsetid & 0x3f) << 6) | (guti->amfpointer & 0x3f);
temp = 0x00 | ((guti->amfsetid) << 6) | (guti->amfpointer & 0x3f);
IES_ENCODE_U16(buffer, encoded, temp);
IES_ENCODE_U32(buffer, encoded, guti->tmsi);
return encoded;
}
static int encode_suci_5gs_mobile_identity(Suci5GSMobileIdentity_t *suci, uint8_t *buffer)
{
uint32_t encoded = 0;
*(buffer + encoded) = 0x00 | (suci->supiformat << 4) | (suci->typeofidentity);
encoded++;
*(buffer + encoded) = 0x00 | ((suci->mccdigit2 & 0xf) << 4) |
(suci->mccdigit1 & 0xf);
encoded++;
*(buffer + encoded) = 0x00 | ((suci->mncdigit3 & 0xf) << 4) |
(suci->mccdigit3 & 0xf);
encoded++;
*(buffer + encoded) = 0x00 | ((suci->mncdigit2 & 0xf) << 4) |
(suci->mncdigit1 & 0xf);
encoded++;
*(buffer + encoded) = 0x00 | ((suci->routingindicatordigit2 & 0xf) << 4) |
(suci->routingindicatordigit1 & 0xf);
encoded++;
*(buffer + encoded) = 0x00 | ((suci->routingindicatordigit4 & 0xf) << 4) |
(suci->routingindicatordigit3 & 0xf);
encoded++;
*(buffer + encoded) = 0x00 | (suci->protectionschemeId & 0xf);
encoded++;
*(buffer + encoded) = suci->homenetworkpki;
encoded++;
IES_ENCODE_U32(buffer, encoded, suci->schemeoutput);
return encoded;
}
static int encode_imeisv_5gs_mobile_identity(Imeisv5GSMobileIdentity_t *imeisv, uint8_t *buffer)
{
uint32_t encoded = 0;
*(buffer + encoded) = 0x00 | (imeisv->digit1 << 4) | (imeisv->oddeven << 3) | (imeisv->typeofidentity);
encoded++;
*(buffer + encoded) = 0x00 | (imeisv->digitp1 << 4) | (imeisv->digitp);
encoded++;
return encoded;
}
@@ -64,6 +64,7 @@ typedef struct {
uint8_t spare6:1;
uint8_t protectionschemeId:4;
uint8_t homenetworkpki;
uint32_t schemeoutput;
} Suci5GSMobileIdentity_t;
typedef struct {
@@ -0,0 +1,41 @@
/*! \file FGSRegistrationResult.c
\brief 5GS Registration result for registration request procedures
\author Yoshio INOUE, Masayuki HARADA
\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com
\date 2020
\version 0.1
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "TLVEncoder.h"
#include "TLVDecoder.h"
#include "FGSRegistrationResult.h"
int decode_fgs_registration_result(FGSRegistrationResult *fgsregistrationresult, uint8_t iei, uint16_t value, uint32_t len)
{
int decoded = 0;
uint16_t *buffer = &value;
fgsregistrationresult->registrationresult = *buffer & 0x7;
fgsregistrationresult->smsallowed = *buffer & 0x8;
decoded = decoded+2;
return decoded;
}
uint16_t encode_fgs_registration_result(FGSRegistrationResult *fgsregistrationresult)
{
uint16_t bufferReturn;
uint16_t *buffer = &bufferReturn;
uint8_t encoded = 0;
*(buffer + encoded) = 0x00 | (fgsregistrationresult->smsallowed & 0x8) |
(fgsregistrationresult->registrationresult & 0x7);
encoded= encoded+2;
return bufferReturn;
}
@@ -0,0 +1,38 @@
/*! \file FGSRegistrationResult.h
\brief 5GS Registration result for registration request procedures
\author Yoshio INOUE, Masayuki HARADA
\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com
\date 2020
\version 0.1
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "OctetString.h"
#ifndef FGS_REGISTRATION_RESULT_H_
#define FGS_REGISTRATION_RESULT_H_
#define FGS_REGISTRATION_RESULT_3GPP 0b001
#define FGS_REGISTRATION_RESULT_NON_3GPP 0b010
#define FGS_REGISTRATION_RESULT_3GPP_AND_NON_3GPP 0b011
typedef struct {
uint8_t iei;
uint8_t resultlength;
uint8_t spare:4;
uint8_t smsallowed:1;
uint8_t registrationresult:3;
} FGSRegistrationResult;
uint16_t encode_fgs_registration_result(FGSRegistrationResult *fgsregistrationresult);
int decode_fgs_registration_result(FGSRegistrationResult *fgsregistrationresult, uint8_t iei, uint16_t value, uint32_t len);
#endif /* FGS REGISTRATION RESULT_H_*/
+491 -28
View File
@@ -35,7 +35,41 @@
#include "TLVDecoder.h"
#include "TLVEncoder.h"
#include "nr_nas_msg_sim.h"
#include "aka_functions.h"
#include "secu_defs.h"
#include "PduSessionEstablishRequest.h"
char netName[] = "5G:mnc093.mcc208.3gppnetwork.org";
char imsi[] = "2089300007487";
// USIM_API_K: 5122250214c33e723a5dd523fc145fc0
uint8_t k[16] = {0x51, 0x22, 0x25, 0x02, 0x14,0xc3, 0x3e, 0x72, 0x3a, 0x5d, 0xd5, 0x23, 0xfc, 0x14, 0x5f, 0xc0};
// OPC: 981d464c7c52eb6e5036234984ad0bcf
const uint8_t opc[16] = {0x98, 0x1d, 0x46, 0x4c,0x7c,0x52,0xeb, 0x6e, 0x50, 0x36, 0x23, 0x49, 0x84, 0xad, 0x0b, 0xcf};
uint8_t *registration_request_buf;
uint32_t registration_request_len;
static int nas_protected_security_header_encode(
char *buffer,
const fgs_nas_message_security_header_t *header,
int length)
{
LOG_FUNC_IN;
int size = 0;
/* Encode the protocol discriminator) */
ENCODE_U8(buffer, header->protocol_discriminator, size);
/* Encode the security header type */
ENCODE_U8(buffer+size, (header->security_header_type & 0xf), size);
/* Encode the message authentication code */
ENCODE_U32(buffer+size, header->message_authentication_code, size);
/* Encode the sequence number */
ENCODE_U8(buffer+size, header->sequence_number, size);
LOG_FUNC_RETURN (size);
}
static int _nas_mm_msg_encode_header(const mm_msg_header_t *header,
uint8_t *buffer, uint32_t len) {
@@ -86,7 +120,18 @@ int mm_msg_encode(MM_msg *mm_msg, uint8_t *buffer, uint32_t len) {
case REGISTRATION_REQUEST:
encode_result = encode_registration_request(&mm_msg->registration_request, buffer, len);
break;
case FGS_IDENTITY_RESPONSE:
encode_result = encode_identiy_response(&mm_msg->fgs_identity_response, buffer, len);
break;
case FGS_AUTHENTICATION_RESPONSE:
encode_result = encode_fgs_authentication_response(&mm_msg->fgs_auth_response, buffer, len);
break;
case FGS_SECURITY_MODE_COMPLETE:
encode_result = encode_fgs_security_mode_complete(&mm_msg->fgs_security_mode_complete, buffer, len);
break;
case FGS_UPLINK_NAS_TRANSPORT:
encode_result = encode_fgs_uplink_nas_transport(&mm_msg->uplink_nas_transport, buffer, len);
break;
default:
LOG_TRACE(ERROR, "EMM-MSG - Unexpected message type: 0x%x",
mm_msg->header.message_type);
@@ -106,7 +151,104 @@ int mm_msg_encode(MM_msg *mm_msg, uint8_t *buffer, uint32_t len) {
LOG_FUNC_RETURN (header_result + encode_result);
}
void transferRES(uint8_t ck[16], uint8_t ik[16], uint8_t *input, uint8_t rand[16], uint8_t *output) {
uint8_t S[100];
S[0] = 0x6B;
int netNamesize = strlen(netName);
memcpy(&S[1], netName, netNamesize);
S[1 + netNamesize] = (netNamesize & 0xff00) >> 8;
S[2 + netNamesize] = (netNamesize & 0x00ff);
for (int i = 0; i < 16; i++)
S[3 + netNamesize + i] = rand[i];
S[19 + netNamesize] = 0x00;
S[20 + netNamesize] = 0x10;
for (int i = 0; i < 8; i++)
S[21 + netNamesize + i] = input[i];
S[29 + netNamesize] = 0x00;
S[30 + netNamesize] = 0x08;
uint8_t plmn[3] = { 0x02, 0xf8, 0x39 };
uint8_t oldS[100];
oldS[0] = 0x6B;
memcpy(&oldS[1], plmn, 3);
oldS[4] = 0x00;
oldS[5] = 0x03;
for (int i = 0; i < 16; i++)
oldS[6 + i] = rand[i];
oldS[22] = 0x00;
oldS[23] = 0x10;
for (int i = 0; i < 8; i++)
oldS[24 + i] = input[i];
oldS[32] = 0x00;
oldS[33] = 0x08;
uint8_t key[32];
memcpy(&key[0], ck, 16);
memcpy(&key[16], ik, 16); //KEY
uint8_t out[32];
kdf(key, 32, S, 31 + netNamesize, out, 32);
for (int i = 0; i < 16; i++)
output[i] = out[16 + i];
}
void derive_kausf(uint8_t ck[16], uint8_t ik[16], uint8_t sqn[6], uint8_t kausf[32]) {
uint8_t S[100];
uint8_t key[32];
int netNamesize = strlen(netName);
memcpy(&key[0], ck, 16);
memcpy(&key[16], ik, 16); //KEY
S[0] = 0x6A;
memcpy(&S[1], netName, netNamesize);
S[1 + netNamesize] = (uint8_t)((netNamesize & 0xff00) >> 8);
S[2 + netNamesize] = (uint8_t)(netNamesize & 0x00ff);
for (int i = 0; i < 6; i++) {
S[3 + netNamesize + i] = sqn[i];
}
S[9 + netNamesize] = 0x00;
S[10 + netNamesize] = 0x06;
kdf(key, 32, S, 11 + netNamesize, kausf, 32);
}
void derive_kseaf(uint8_t kausf[32], uint8_t kseaf[32]) {
uint8_t S[100];
int netNamesize = strlen(netName);
S[0] = 0x6C; //FC
memcpy(&S[1], netName, netNamesize);
S[1 + netNamesize] = (uint8_t)((netNamesize & 0xff00) >> 8);
S[2 + netNamesize] = (uint8_t)(netNamesize & 0x00ff);
kdf(kausf, 32, S, 3 + netNamesize, kseaf, 32);
}
void derive_kamf(uint8_t *kseaf, uint8_t *kamf, uint16_t abba) {
int imsiLen = strlen(imsi);
uint8_t S[100];
S[0] = 0x6D; //FC = 0x6D
memcpy(&S[1], imsi, imsiLen);
S[1 + imsiLen] = (uint8_t)((imsiLen & 0xff00) >> 8);
S[2 + imsiLen] = (uint8_t)(imsiLen & 0x00ff);
S[3 + imsiLen] = abba & 0x00ff;
S[4 + imsiLen] = (abba & 0xff00) >> 8;
S[5 + imsiLen] = 0x00;
S[6 + imsiLen] = 0x02;
kdf(kseaf, 32, S, 7 + imsiLen, kamf, 32);
}
//------------------------------------------------------------------------------
void derive_knas(algorithm_type_dist_t nas_alg_type, uint8_t nas_alg_id, uint8_t kamf[32], uint8_t *knas_int) {
uint8_t S[20];
uint8_t out[32] = { 0 };
S[0] = 0x69; //FC
S[1] = (uint8_t)(nas_alg_type & 0xFF);
S[2] = 0x00;
S[3] = 0x01;
S[4] = nas_alg_id;
S[5] = 0x00;
S[6] = 0x01;
kdf(kamf, 32, S, 7, out, 32);
for (int i = 0; i < 16; i++)
knas_int[i] = out[16 + i];
}
void generateRegistrationRequest(as_nas_info_t *initialNasMsg) {
int size = sizeof(mm_msg_header_t);
@@ -129,20 +271,35 @@ void generateRegistrationRequest(as_nas_info_t *initialNasMsg) {
mm_msg->registration_request.messagetype = REGISTRATION_REQUEST;
size += 1;
mm_msg->registration_request.fgsregistrationtype = INITIAL_REGISTRATION;
mm_msg->registration_request.naskeysetidentifier.naskeysetidentifier = NAS_KEY_SET_IDENTIFIER_NOT_AVAILABLE;
mm_msg->registration_request.naskeysetidentifier.naskeysetidentifier = 1;
size += 1;
mm_msg->registration_request.fgsmobileidentity.guti.typeofidentity = FGS_MOBILE_IDENTITY_5G_GUTI;
// mm_msg->registration_request.fgsmobileidentity.guti.amfregionid = 1;
// mm_msg->registration_request.fgsmobileidentity.guti.amfpointer = 1;
// mm_msg->registration_request.fgsmobileidentity.guti.amfsetid = 1;
mm_msg->registration_request.fgsmobileidentity.guti.tmsi = 10;
mm_msg->registration_request.fgsmobileidentity.guti.mncdigit1 = 9;
mm_msg->registration_request.fgsmobileidentity.guti.mncdigit2 = 3;
mm_msg->registration_request.fgsmobileidentity.guti.mccdigit1 = 2;
mm_msg->registration_request.fgsmobileidentity.guti.mccdigit2 = 0;
mm_msg->registration_request.fgsmobileidentity.guti.mccdigit3 = 8;
if(1){
mm_msg->registration_request.fgsmobileidentity.guti.typeofidentity = FGS_MOBILE_IDENTITY_5G_GUTI;
mm_msg->registration_request.fgsmobileidentity.guti.amfregionid = 0xca;
mm_msg->registration_request.fgsmobileidentity.guti.amfpointer = 0;
mm_msg->registration_request.fgsmobileidentity.guti.amfsetid = 1016;
mm_msg->registration_request.fgsmobileidentity.guti.tmsi = 10;
mm_msg->registration_request.fgsmobileidentity.guti.mncdigit1 = 9;
mm_msg->registration_request.fgsmobileidentity.guti.mncdigit2 = 3;
mm_msg->registration_request.fgsmobileidentity.guti.mncdigit3 = 0xf;
mm_msg->registration_request.fgsmobileidentity.guti.mccdigit1 = 2;
mm_msg->registration_request.fgsmobileidentity.guti.mccdigit2 = 0;
mm_msg->registration_request.fgsmobileidentity.guti.mccdigit3 = 8;
size += 13;
size += 13;
} else {
mm_msg->registration_request.fgsmobileidentity.suci.typeofidentity = FGS_MOBILE_IDENTITY_SUCI;
mm_msg->registration_request.fgsmobileidentity.suci.mncdigit1 = 9;
mm_msg->registration_request.fgsmobileidentity.suci.mncdigit2 = 3;
mm_msg->registration_request.fgsmobileidentity.suci.mncdigit3 = 0xf;
mm_msg->registration_request.fgsmobileidentity.suci.mccdigit1 = 2;
mm_msg->registration_request.fgsmobileidentity.suci.mccdigit2 = 0;
mm_msg->registration_request.fgsmobileidentity.suci.mccdigit3 = 8;
mm_msg->registration_request.fgsmobileidentity.suci.schemeoutput = 0x4778;
size += 14;
}
mm_msg->registration_request.presencemask |= REGISTRATION_REQUEST_5GMM_CAPABILITY_PRESENT;
mm_msg->registration_request.fgmmcapability.iei = REGISTRATION_REQUEST_5GMM_CAPABILITY_IEI;
@@ -161,16 +318,218 @@ void generateRegistrationRequest(as_nas_info_t *initialNasMsg) {
// encode the message
initialNasMsg->data = (Byte_t *)malloc(size * sizeof(Byte_t));
registration_request_buf = initialNasMsg->data;
initialNasMsg->length = mm_msg_encode(mm_msg, (uint8_t*)(initialNasMsg->data), size);
registration_request_len = initialNasMsg->length;
}
void generateRegistrationComplete(as_nas_info_t *ulNasMsg, SORTransparentContainer *sortransparentcontainer) {
int length = sizeof(fgs_nas_message_security_header_t);
void generateIdentityResponse(as_nas_info_t *initialNasMsg, uint8_t identitytype) {
int size = sizeof(mm_msg_header_t);
fgs_nas_message_t nas_msg;
memset(&nas_msg, 0, sizeof(fgs_nas_message_t));
MM_msg *mm_msg;
mm_msg = &nas_msg.plain.mm_msg;
// set header
mm_msg->header.ex_protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE;
mm_msg->header.security_header_type = PLAIN_5GS_MSG;
mm_msg->header.message_type = FGS_IDENTITY_RESPONSE;
// set identity response
mm_msg->fgs_identity_response.protocoldiscriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE;
size += 1;
mm_msg->fgs_identity_response.securityheadertype = PLAIN_5GS_MSG;
size += 1;
mm_msg->fgs_identity_response.messagetype = FGS_IDENTITY_RESPONSE;
size += 1;
if(identitytype == FGS_MOBILE_IDENTITY_SUCI){
mm_msg->fgs_identity_response.fgsmobileidentity.suci.typeofidentity = FGS_MOBILE_IDENTITY_SUCI;
mm_msg->fgs_identity_response.fgsmobileidentity.suci.mncdigit1 = 9;
mm_msg->fgs_identity_response.fgsmobileidentity.suci.mncdigit2 = 3;
mm_msg->fgs_identity_response.fgsmobileidentity.suci.mncdigit3 = 0xf;
mm_msg->fgs_identity_response.fgsmobileidentity.suci.mccdigit1 = 2;
mm_msg->fgs_identity_response.fgsmobileidentity.suci.mccdigit2 = 0;
mm_msg->fgs_identity_response.fgsmobileidentity.suci.mccdigit3 = 8;
mm_msg->fgs_identity_response.fgsmobileidentity.suci.schemeoutput = 0x4778;
size += 14;
}
// encode the message
initialNasMsg->data = (Byte_t *)malloc(size * sizeof(Byte_t));
initialNasMsg->length = mm_msg_encode(mm_msg, (uint8_t*)(initialNasMsg->data), size);
}
OctetString knas_int;
void generateAuthenticationResp(as_nas_info_t *initialNasMsg, uint8_t *buf){
uint8_t ak[6];
uint8_t kausf[32];
uint8_t sqn[6];
uint8_t kseaf[32];
uint8_t kamf[32];
OctetString res;
// get RAND for authentication request
unsigned char rand[16];
for(int index = 0; index < 16;index++){
rand[index] = buf[8+index];
}
uint8_t resTemp[16];
uint8_t ck[16], ik[16], output[16];
f2345(k, rand, resTemp, ck, ik, ak, opc);
transferRES(ck, ik, resTemp, rand, output);
// get knas_int
knas_int.length = 16;
knas_int.value = malloc(knas_int.length);
for(int index = 0; index < 6; index++){
sqn[index] = buf[26+index];
}
derive_kausf(ck, ik, sqn, kausf);
derive_kseaf(kausf, kseaf);
derive_kamf(kseaf, kamf, 0x0000);
derive_knas(0x02, 2, kamf, knas_int.value);
printf("kausf:");
for(int i = 0; i < 32; i++){
printf("%x ", kausf[i]);
}
printf("\n");
printf("kseaf:");
for(int i = 0; i < 32; i++){
printf("%x ", kseaf[i]);
}
printf("\n");
printf("kamf:");
for(int i = 0; i < 32; i++){
printf("%x ", kamf[i]);
}
printf("\n");
printf("knas_int:\n");
for(int i = 0; i < 16; i++){
printf("%x ", knas_int.value[i]);
}
printf("\n");
// set res
res.length = 16;
res.value = output;
int size = sizeof(mm_msg_header_t);
fgs_nas_message_t nas_msg;
memset(&nas_msg, 0, sizeof(fgs_nas_message_t));
MM_msg *mm_msg;
mm_msg = &nas_msg.plain.mm_msg;
// set header
mm_msg->header.ex_protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE;
mm_msg->header.security_header_type = PLAIN_5GS_MSG;
mm_msg->header.message_type = FGS_AUTHENTICATION_RESPONSE;
// set authentication response
mm_msg->fgs_identity_response.protocoldiscriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE;
size += 1;
mm_msg->fgs_identity_response.securityheadertype = PLAIN_5GS_MSG;
size += 1;
mm_msg->fgs_identity_response.messagetype = FGS_AUTHENTICATION_RESPONSE;
size += 1;
//set response parameter
mm_msg->fgs_auth_response.authenticationresponseparameter.res = res;
size += 18;
// encode the message
initialNasMsg->data = (Byte_t *)malloc(size * sizeof(Byte_t));
initialNasMsg->length = mm_msg_encode(mm_msg, (uint8_t*)(initialNasMsg->data), size);
}
void generateSecurityModeComplete(as_nas_info_t *initialNasMsg)
{
int size = sizeof(mm_msg_header_t);
fgs_nas_message_t nas_msg;
memset(&nas_msg, 0, sizeof(fgs_nas_message_t));
MM_msg *mm_msg;
nas_stream_cipher_t stream_cipher;
uint8_t mac[4];
// set security protected header
nas_msg.header.protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE;
nas_msg.header.security_header_type = INTEGRITY_PROTECTED_AND_CIPHERED_WITH_NEW_SECU_CTX;
size += 7;
mm_msg = &nas_msg.security_protected.plain.mm_msg;
// set header
mm_msg->header.ex_protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE;
mm_msg->header.security_header_type = PLAIN_5GS_MSG;
mm_msg->header.message_type = FGS_SECURITY_MODE_COMPLETE;
// set security mode complete
mm_msg->fgs_security_mode_complete.protocoldiscriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE;
size += 1;
mm_msg->fgs_security_mode_complete.securityheadertype = PLAIN_5GS_MSG;
size += 1;
mm_msg->fgs_security_mode_complete.messagetype = FGS_SECURITY_MODE_COMPLETE;
size += 1;
mm_msg->fgs_security_mode_complete.fgsmobileidentity.imeisv.typeofidentity = FGS_MOBILE_IDENTITY_IMEISV;
mm_msg->fgs_security_mode_complete.fgsmobileidentity.imeisv.digit1 = 1;
mm_msg->fgs_security_mode_complete.fgsmobileidentity.imeisv.digitp1 = 1;
mm_msg->fgs_security_mode_complete.fgsmobileidentity.imeisv.digitp = 1;
mm_msg->fgs_security_mode_complete.fgsmobileidentity.imeisv.oddeven = 0;
size += 5;
mm_msg->fgs_security_mode_complete.fgsnasmessagecontainer.nasmessagecontainercontents.value = registration_request_buf;
mm_msg->fgs_security_mode_complete.fgsnasmessagecontainer.nasmessagecontainercontents.length = registration_request_len;
size += (registration_request_len + 2);
// encode the message
initialNasMsg->data = (Byte_t *)malloc(size * sizeof(Byte_t));
int security_header_len = nas_protected_security_header_encode((char*)(initialNasMsg->data),&(nas_msg.header), size);
initialNasMsg->length = security_header_len + mm_msg_encode(mm_msg, (uint8_t*)(initialNasMsg->data+security_header_len), size-security_header_len);
stream_cipher.key = knas_int.value;
stream_cipher.key_length = 16;
stream_cipher.count = 0;
stream_cipher.bearer = 1;
stream_cipher.direction = 0;
stream_cipher.message = (unsigned char *)(initialNasMsg->data + 6);
/* length in bits */
stream_cipher.blength = (initialNasMsg->length - 6) << 3;
// only for Type of integrity protection algorithm: 128-5G-IA2 (2)
nas_stream_encrypt_eia2(
&stream_cipher,
mac);
printf("mac %x %x %x %x \n", mac[0], mac[1], mac[2], mac[3]);
for(int i = 0; i < 4; i++){
initialNasMsg->data[2+i] = mac[i];
}
}
void generateRegistrationComplete(as_nas_info_t *initialNasMsg, SORTransparentContainer *sortransparentcontainer) {
int length = 0;
int size = 0;
fgs_nas_message_t nas_msg;
nas_stream_cipher_t stream_cipher;
uint8_t mac[4];
memset(&nas_msg, 0, sizeof(fgs_nas_message_t));
fgs_nas_message_security_protected_t *sp_msg;
@@ -178,15 +537,15 @@ void generateRegistrationComplete(as_nas_info_t *ulNasMsg, SORTransparentContain
// set header
sp_msg->header.protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE;
sp_msg->header.security_header_type = INTEGRITY_PROTECTED_AND_CIPHERED;
sp_msg->header.message_authentication_code = 0x8fc59d96;
sp_msg->header.message_authentication_code = 0;
sp_msg->header.sequence_number = 1;
length = 7;
sp_msg->plain.mm_msg.registration_complete.protocoldiscriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE;
length += 1;
sp_msg->plain.mm_msg.registration_complete.securityheadertype = PLAIN_5GS_MSG;
sp_msg->plain.mm_msg.registration_complete.sparehalfoctet = 0;
length += 1;
sp_msg->plain.mm_msg.registration_complete.messagetype = REGISTRATION_REQUEST;
sp_msg->plain.mm_msg.registration_complete.messagetype = REGISTRATION_COMPLETE;
length += 1;
if(sortransparentcontainer) {
@@ -194,32 +553,136 @@ void generateRegistrationComplete(as_nas_info_t *ulNasMsg, SORTransparentContain
}
// encode the message
ulNasMsg->data = (Byte_t *)malloc(length * sizeof(Byte_t));
initialNasMsg->data = (Byte_t *)malloc(length * sizeof(Byte_t));
/* Encode the first octet of the header (extended protocol discriminator) */
ENCODE_U8(ulNasMsg->data + size, sp_msg->header.protocol_discriminator, size);
ENCODE_U8(initialNasMsg->data + size, sp_msg->header.protocol_discriminator, size);
/* Encode the security header type */
ENCODE_U8(ulNasMsg->data + size, sp_msg->header.security_header_type, size);
ENCODE_U8(initialNasMsg->data + size, sp_msg->header.security_header_type, size);
/* Encode the message authentication code */
ENCODE_U32(ulNasMsg->data + size, sp_msg->header.message_authentication_code, size);
ENCODE_U32(initialNasMsg->data + size, sp_msg->header.message_authentication_code, size);
/* Encode the sequence number */
ENCODE_U8(ulNasMsg->data + size, sp_msg->header.sequence_number, size);
ENCODE_U8(initialNasMsg->data + size, sp_msg->header.sequence_number, size);
/* Encode the extended protocol discriminator */
ENCODE_U8(ulNasMsg->data + size, sp_msg->plain.mm_msg.registration_complete.protocoldiscriminator, size);
ENCODE_U8(initialNasMsg->data + size, sp_msg->plain.mm_msg.registration_complete.protocoldiscriminator, size);
/* Encode the security header type */
ENCODE_U8(ulNasMsg->data + size, sp_msg->plain.mm_msg.registration_complete.securityheadertype, size);
ENCODE_U8(initialNasMsg->data + size, sp_msg->plain.mm_msg.registration_complete.securityheadertype, size);
/* Encode the message type */
ENCODE_U8(ulNasMsg->data + size, sp_msg->plain.mm_msg.registration_complete.messagetype, size);
ENCODE_U8(initialNasMsg->data + size, sp_msg->plain.mm_msg.registration_complete.messagetype, size);
if(sortransparentcontainer) {
encode_registration_complete(&sp_msg->plain.mm_msg.registration_complete, ulNasMsg->data + size, length - size);
encode_registration_complete(&sp_msg->plain.mm_msg.registration_complete, initialNasMsg->data + size, length - size);
}
initialNasMsg->length = length;
stream_cipher.key = knas_int.value;
stream_cipher.key_length = 16;
stream_cipher.count = 1;
stream_cipher.bearer = 1;
stream_cipher.direction = 0;
stream_cipher.message = (unsigned char *)(initialNasMsg->data + 6);
/* length in bits */
stream_cipher.blength = (initialNasMsg->length - 6) << 3;
// only for Type of integrity protection algorithm: 128-5G-IA2 (2)
nas_stream_encrypt_eia2(
&stream_cipher,
mac);
printf("mac %x %x %x %x \n", mac[0], mac[1], mac[2], mac[3]);
for(int i = 0; i < 4; i++){
initialNasMsg->data[2+i] = mac[i];
}
}
void generatePduSessionEstablishRequest(as_nas_info_t *initialNasMsg){
int size = 0;
fgs_nas_message_t nas_msg;
memset(&nas_msg, 0, sizeof(fgs_nas_message_t));
// setup pdu session establishment request
uint16_t req_length = 6;
uint8_t *req_buffer = malloc(req_length);
pdu_session_establishment_request_msg pdu_session_establish;
pdu_session_establish.protocoldiscriminator = FGS_SESSION_MANAGEMENT_MESSAGE;
pdu_session_establish.pdusessionid = 10;
pdu_session_establish.pti = 0;
pdu_session_establish.pdusessionestblishmsgtype = FGS_PDU_SESSION_ESTABLISHMENT_REQ;
pdu_session_establish.maxdatarate = 0xffff;
encode_pdu_session_establishment_request(&pdu_session_establish, req_buffer);
MM_msg *mm_msg;
nas_stream_cipher_t stream_cipher;
uint8_t mac[4];
uint8_t nssai[]={1,1,2,3};
uint8_t dnn[9]={0x8,0x69,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74};
// set security protected header
nas_msg.header.protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE;
nas_msg.header.security_header_type = INTEGRITY_PROTECTED_AND_CIPHERED_WITH_NEW_SECU_CTX;
size += 7;
mm_msg = &nas_msg.security_protected.plain.mm_msg;
// set header
mm_msg->header.ex_protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE;
mm_msg->header.security_header_type = PLAIN_5GS_MSG;
mm_msg->header.message_type = FGS_UPLINK_NAS_TRANSPORT;
// set uplink nas transport
mm_msg->uplink_nas_transport.protocoldiscriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE;
size += 1;
mm_msg->uplink_nas_transport.securityheadertype = PLAIN_5GS_MSG;
size += 1;
mm_msg->uplink_nas_transport.messagetype = FGS_UPLINK_NAS_TRANSPORT;
size += 1;
mm_msg->uplink_nas_transport.payloadcontainertype.iei = 0;
mm_msg->uplink_nas_transport.payloadcontainertype.type = 1;
size += 1;
mm_msg->uplink_nas_transport.fgspayloadcontainer.payloadcontainercontents.length = req_length;
mm_msg->uplink_nas_transport.fgspayloadcontainer.payloadcontainercontents.value = req_buffer;
size += (2+req_length);
mm_msg->uplink_nas_transport.pdusessionid = 10;
mm_msg->uplink_nas_transport.requesttype = 1;
size += 3;
mm_msg->uplink_nas_transport.snssai.length = 4;
mm_msg->uplink_nas_transport.snssai.value = nssai;
size += (1+1+4);
mm_msg->uplink_nas_transport.dnn.length = 9;
mm_msg->uplink_nas_transport.dnn.value = dnn;
size += (1+1+9);
// encode the message
initialNasMsg->data = (Byte_t *)malloc(size * sizeof(Byte_t));
int security_header_len = nas_protected_security_header_encode((char*)(initialNasMsg->data),&(nas_msg.header), size);
initialNasMsg->length = security_header_len + mm_msg_encode(mm_msg, (uint8_t*)(initialNasMsg->data+security_header_len), size-security_header_len);
stream_cipher.key = knas_int.value;
stream_cipher.key_length = 16;
stream_cipher.count = 0;
stream_cipher.bearer = 1;
stream_cipher.direction = 0;
stream_cipher.message = (unsigned char *)(initialNasMsg->data + 6);
/* length in bits */
stream_cipher.blength = (initialNasMsg->length - 6) << 3;
// only for Type of integrity protection algorithm: 128-5G-IA2 (2)
nas_stream_encrypt_eia2(
&stream_cipher,
mac);
printf("mac %x %x %x %x \n", mac[0], mac[1], mac[2], mac[3]);
for(int i = 0; i < 4; i++){
initialNasMsg->data[2+i] = mac[i];
}
}
+30 -13
View File
@@ -33,16 +33,18 @@
#define __NR_NAS_MSG_SIM_H__
#include "RegistrationRequest.h"
#include "FGSIdentityResponse.h"
#include "FGSAuthenticationResponse.h"
#include "FGSNASSecurityModeComplete.h"
#include "RegistrationComplete.h"
#include "as_message.h"
#include "FGSUplinkNasTransport.h"
#define PLAIN_5GS_MSG 0b0000
#define INTEGRITY_PROTECTED 0b0001
#define INTEGRITY_PROTECTED_AND_CIPHERED 0b0010
#define INITIAL_REGISTRATION 0b001
#define INTEGRITY_PROTECTED_WITH_NEW_SECU_CTX 0b0011 // only for SECURITY MODE COMMAND
#define INTEGRITY_PROTECTED_AND_CIPHERED_WITH_NEW_SECU_CTX 0b0100 // only for SECURITY MODE COMPLETE
#define REGISTRATION_REQUEST 0b01000001 /* 65 = 0x41 */
#define REGISTRATION_ACCEPT 0b01000010 /* 66 = 0x42 */
@@ -56,25 +58,28 @@
#define FIVEGMM_SERVICE_REQUEST 0b01001100 /* 76 = 0x4c */
#define FIVEGMM_SERVICE_REJECT 0b01001101 /* 77 = 0x4d */
#define FIVEGMM_SERVICE_ACCEPT 0b01001110 /* 78 = 0x4e */
#define CONFIGURATION_UPDATE_COMMAND 0b01010100 /* 84 = 0x54 */
#define CONFIGURATION_UPDATE_COMPLETE 0b01010101 /* 85 = 0x55 */
#define AUTHENTICATION_REQUEST 0b01010110 /* 86 = 0x56 */
#define AUTHENTICATION_RESPONSE 0b01010111 /* 87 = 0x57 */
#define FGS_AUTHENTICATION_REQUEST 0b01010110 /* 86 = 0x56 */
#define FGS_AUTHENTICATION_RESPONSE 0b01010111 /* 87 = 0x57 */
#define AUTHENTICATION_REJECT 0b01011000 /* 88 = 0x58 */
#define AUTHENTICATION_FAILURE 0b01011001 /* 89 = 0x59 */
#define AUTHENTICATION_RESULT 0b01011010 /* 90 = 0x5a */
#define FIVEGMM_IDENTITY_REQUEST 0b01011011 /* 91 = 0x5b */
#define FIVEGMM_IDENTITY_RESPONSE 0b01011100 /* 92 = 0x5c */
#define FIVEGMM_SECURITY_MODE_COMMAND 0b01011101 /* 93 = 0x5d */
#define FIVEGMM_SECURITY_MODE_COMPLETE 0b01011110 /* 94 = 0x5e */
#define FGS_IDENTITY_REQUEST 0b01011011 /* 91 = 0x5b */
#define FGS_IDENTITY_RESPONSE 0b01011100 /* 92 = 0x5c */
#define FGS_SECURITY_MODE_COMMAND 0b01011101 /* 93 = 0x5d */
#define FGS_SECURITY_MODE_COMPLETE 0b01011110 /* 94 = 0x5e */
#define FIVEGMM_SECURITY_MODE_REJECT 0b01011111 /* 95 = 0x5f */
#define FIVEGMM_STATUS 0b01100100 /* 100 = 0x64 */
#define NOTIFICATION 0b01100101 /* 101 = 0x65 */
#define NOTIFICATION_RESPONSE 0b01100110 /* 102 = 0x66 */
#define UL_NAS_TRANSPORT 0b01100111 /* 103 = 0x67 */
#define FGS_UPLINK_NAS_TRANSPORT 0b01100111 /* 103= 0x67 */
#define DL_NAS_TRANSPORT 0b01101000 /* 104 = 0x68 */
// message type for 5GS session management
#define FGS_PDU_SESSION_ESTABLISHMENT_REQ 0b11000001 /* 193= 0xc1 */
#define INITIAL_REGISTRATION 0b001
typedef enum fgs_protocol_discriminator_e {
@@ -103,7 +108,11 @@ typedef struct {
typedef union {
mm_msg_header_t header;
registration_request_msg registration_request;
fgs_identiy_response_msg fgs_identity_response;
fgs_authentication_response_msg fgs_auth_response;
fgs_security_mode_complete_msg fgs_security_mode_complete;
registration_complete_msg registration_complete;
fgs_uplink_nas_transport_msg uplink_nas_transport;
} MM_msg;
@@ -125,5 +134,13 @@ typedef union {
} fgs_nas_message_t;
void generateRegistrationRequest(as_nas_info_t *initialNasMsg);
void generateRegistrationComplete(as_nas_info_t *ulNasMsg, SORTransparentContainer *sortransparentcontainer);
void generateIdentityResponse(as_nas_info_t *initialNasMsg, uint8_t identitytype);
void generateAuthenticationResp(as_nas_info_t *initialNasMsg, uint8_t *buf);
void generateSecurityModeComplete(as_nas_info_t *initialNasMsg);
void generateRegistrationComplete(as_nas_info_t *initialNasMsg, SORTransparentContainer *sortransparentcontainer);
void generatePduSessionEstablishRequest(as_nas_info_t *initialNasMsg);
#endif /* __NR_NAS_MSG_SIM_H__*/
@@ -49,6 +49,7 @@
#include "ngap_gNB_nas_procedures.h"
#include "ngap_gNB_management_procedures.h"
#include "ngap_gNB_context_management_procedures.h"
#include "NGAP_PDUSessionResourceItemCxtRelReq.h"
#include "msc.h"
@@ -203,6 +204,21 @@ int ngap_ue_context_release_req(instance_t instance,
ie->value.choice.RAN_UE_NGAP_ID = ue_release_req_p->gNB_ue_ngap_id;
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
/* optional */
if (ue_release_req_p->nb_of_pdusessions > 0) {
ie = (NGAP_UEContextReleaseRequest_IEs_t *)calloc(1, sizeof(NGAP_UEContextReleaseRequest_IEs_t));
ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceListCxtRelReq;
ie->criticality = NGAP_Criticality_reject;
ie->value.present = NGAP_UEContextReleaseRequest_IEs__value_PR_PDUSessionResourceListCxtRelReq;
for (int i = 0; i < ue_release_req_p->nb_of_pdusessions; i++) {
NGAP_PDUSessionResourceItemCxtRelReq_t *item;
item = (NGAP_PDUSessionResourceItemCxtRelReq_t *)calloc(1,sizeof(NGAP_PDUSessionResourceItemCxtRelReq_t));
item->pDUSessionID = ue_release_req_p->pdusessions[i].pdusession_id;
ASN_SEQUENCE_ADD(&ie->value.choice.PDUSessionResourceListCxtRelReq.list, item);
}
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
}
/* mandatory */
ie = (NGAP_UEContextReleaseRequest_IEs_t *)calloc(1, sizeof(NGAP_UEContextReleaseRequest_IEs_t));
ie->id = NGAP_ProtocolIE_ID_id_Cause;
+1 -1
View File
@@ -73,7 +73,7 @@ int ngap_gNB_encode_pdu(NGAP_NGAP_PDU_t *pdu, uint8_t **buffer, uint32_t *len) {
return -1;
}
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, pdu);
//ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, pdu);
return ret;
}
+23 -17
View File
@@ -49,6 +49,7 @@
#include "assertions.h"
#include "conversions.h"
#include "msc.h"
#include "NGAP_NonDynamic5QIDescriptor.h"
static
int ngap_gNB_handle_ng_setup_response(uint32_t assoc_id,
@@ -882,11 +883,11 @@ int ngap_gNB_handle_initial_context_request(uint32_t assoc_id,
}
/* Initial context request = UE-related procedure -> stream != 0 */
if (stream == 0) {
NGAP_ERROR("[SCTP %d] Received UE-related procedure on stream (%d)\n",
assoc_id, stream);
return -1;
}
//if (stream == 0) {
// NGAP_ERROR("[SCTP %d] Received UE-related procedure on stream (%d)\n",
// assoc_id, stream);
// return -1;
//}
ue_desc_p->rx_stream = stream;
ue_desc_p->amf_ue_ngap_id = amf_ue_ngap_id;
@@ -955,7 +956,7 @@ int ngap_gNB_handle_initial_context_request(uint32_t assoc_id,
}
dec_rval = uper_decode(NULL,
dec_rval = aper_decode(NULL,
&asn_DEF_NGAP_PDUSessionResourceSetupRequestTransfer,
(void **)&pdusessionTransfer_p,
item_p->pDUSessionResourceSetupRequestTransfer.buf,
@@ -1028,7 +1029,7 @@ int ngap_gNB_handle_initial_context_request(uint32_t assoc_id,
qosFlowItem_p = pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.array[qosIdx];
/* Set the QOS informations */
NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].qos[qosIdx].qci = (uint8_t)qosFlowItem_p->qosFlowIdentifier;
NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier;
NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].qos[qosIdx].allocation_retention_priority.priority_level =
qosFlowItem_p->qosFlowLevelQosParameters.allocationAndRetentionPriority.priorityLevelARP;
@@ -1289,11 +1290,11 @@ int ngap_gNB_handle_pdusession_setup_request(uint32_t assoc_id,
}
/* Initial context request = UE-related procedure -> stream != 0 */
if (stream == 0) {
NGAP_ERROR("[SCTP %d] Received UE-related procedure on stream (%d)\n",
assoc_id, stream);
return -1;
}
// if (stream == 0) {
// NGAP_ERROR("[SCTP %d] Received UE-related procedure on stream (%d)\n",
// assoc_id, stream);
// return -1;
// }
ue_desc_p->rx_stream = stream;
@@ -1338,7 +1339,7 @@ int ngap_gNB_handle_pdusession_setup_request(uint32_t assoc_id,
NGAP_WARN("NAS PDU is not provided, generate a PDUSESSION_SETUP Failure (TBD) back to AMF \n");
}
dec_rval = uper_decode(NULL,
dec_rval = aper_decode(NULL,
&asn_DEF_NGAP_PDUSessionResourceSetupRequestTransfer,
(void **)&pdusessionTransfer_p,
item_p->pDUSessionResourceSetupRequestTransfer.buf,
@@ -1407,8 +1408,13 @@ int ngap_gNB_handle_pdusession_setup_request(uint32_t assoc_id,
qosFlowItem_p = pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.array[qosIdx];
/* Set the QOS informations */
NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].qos[qosIdx].qci = (uint8_t)qosFlowItem_p->qosFlowIdentifier;
NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier;
if(qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics.present == NGAP_QosCharacteristics_PR_nonDynamic5QI){
if(qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics.choice.nonDynamic5QI != NULL){
NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].qos[qosIdx].fiveQI =
(uint64_t)qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics.choice.nonDynamic5QI->fiveQI;
}
}
NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].qos[qosIdx].allocation_retention_priority.priority_level =
qosFlowItem_p->qosFlowLevelQosParameters.allocationAndRetentionPriority.priorityLevelARP;
NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].qos[qosIdx].allocation_retention_priority.pre_emp_capability =
@@ -1668,7 +1674,7 @@ int ngap_gNB_handle_pdusession_modify_request(uint32_t assoc_id,
continue;
}
dec_rval = uper_decode(NULL,
dec_rval = aper_decode(NULL,
&asn_DEF_NGAP_PDUSessionResourceModifyRequestTransfer,
(void **)&pdusessionTransfer_p,
item_p->pDUSessionResourceModifyRequestTransfer.buf,
@@ -1709,7 +1715,7 @@ int ngap_gNB_handle_pdusession_modify_request(uint32_t assoc_id,
qosFlowItem_p = pdusessionTransfer_ies->value.choice.QosFlowAddOrModifyRequestList.list.array[qosIdx];
/* Set the QOS informations */
NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].qos[qosIdx].qci = (uint8_t)qosFlowItem_p->qosFlowIdentifier;
NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier;
if(qosFlowItem_p->qosFlowLevelQosParameters) {
NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].qos[qosIdx].allocation_retention_priority.priority_level =
qosFlowItem_p->qosFlowLevelQosParameters->allocationAndRetentionPriority.priorityLevelARP;
+72 -54
View File
@@ -469,6 +469,7 @@ int ngap_gNB_nas_uplink(instance_t instance, ngap_uplink_nas_t *ngap_uplink_nas_
/* Prepare the NGAP message to encode */
memset(&pdu, 0, sizeof(pdu));
pdu.present = NGAP_NGAP_PDU_PR_initiatingMessage;
pdu.choice.initiatingMessage = (NGAP_InitiatingMessage_t *)calloc(1,sizeof(NGAP_InitiatingMessage_t));
pdu.choice.initiatingMessage->procedureCode = NGAP_ProcedureCode_id_UplinkNASTransport;
pdu.choice.initiatingMessage->criticality = NGAP_Criticality_ignore;
pdu.choice.initiatingMessage->value.present = NGAP_InitiatingMessage__value_PR_UplinkNASTransport;
@@ -503,6 +504,7 @@ int ngap_gNB_nas_uplink(instance_t instance, ngap_uplink_nas_t *ngap_uplink_nas_
ie->value.present = NGAP_UplinkNASTransport_IEs__value_PR_UserLocationInformation;
ie->value.choice.UserLocationInformation.present = NGAP_UserLocationInformation_PR_userLocationInformationNR;
ie->value.choice.UserLocationInformation.choice.userLocationInformationNR = CALLOC(1,sizeof(struct NGAP_UserLocationInformationNR));
userinfo_nr_p = ie->value.choice.UserLocationInformation.choice.userLocationInformationNR;
/* Set nRCellIdentity. default userLocationInformationNR */
@@ -685,6 +687,7 @@ int ngap_gNB_initial_ctxt_resp(
/* Prepare the NGAP message to encode */
memset(&pdu, 0, sizeof(pdu));
pdu.present = NGAP_NGAP_PDU_PR_successfulOutcome;
pdu.choice.successfulOutcome = (NGAP_SuccessfulOutcome_t *)calloc(1,sizeof(struct NGAP_SuccessfulOutcome));
pdu.choice.successfulOutcome->procedureCode = NGAP_ProcedureCode_id_InitialContextSetup;
pdu.choice.successfulOutcome->criticality = NGAP_Criticality_reject;
pdu.choice.successfulOutcome->value.present = NGAP_SuccessfulOutcome__value_PR_InitialContextSetupResponse;
@@ -710,67 +713,68 @@ int ngap_gNB_initial_ctxt_resp(
ie->criticality = NGAP_Criticality_ignore;
ie->value.present = NGAP_InitialContextSetupResponseIEs__value_PR_PDUSessionResourceSetupListCxtRes;
for (i = 0; i < initial_ctxt_resp_p->nb_of_pdusessions; i++) {
NGAP_PDUSessionResourceSetupItemCxtRes_t *item;
NGAP_PDUSessionResourceSetupResponseTransfer_t *pdusessionTransfer_p = NULL;
/* mandatory */
item = (NGAP_PDUSessionResourceSetupItemCxtRes_t *)calloc(1, sizeof(NGAP_PDUSessionResourceSetupItemCxtRes_t));
if (initial_ctxt_resp_p->nb_of_pdusessions){
for (i = 0; i < initial_ctxt_resp_p->nb_of_pdusessions; i++) {
NGAP_PDUSessionResourceSetupItemCxtRes_t *item;
NGAP_PDUSessionResourceSetupResponseTransfer_t *pdusessionTransfer_p = NULL;
/* pDUSessionID */
item->pDUSessionID = initial_ctxt_resp_p->pdusessions[i].pdusession_id;
/* mandatory */
item = (NGAP_PDUSessionResourceSetupItemCxtRes_t *)calloc(1, sizeof(NGAP_PDUSessionResourceSetupItemCxtRes_t));
/* dLQosFlowPerTNLInformation */
pdusessionTransfer_p = (NGAP_PDUSessionResourceSetupResponseTransfer_t *)calloc(1, sizeof(NGAP_PDUSessionResourceSetupResponseTransfer_t));
/* pDUSessionID */
item->pDUSessionID = initial_ctxt_resp_p->pdusessions[i].pdusession_id;
pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.present = NGAP_UPTransportLayerInformation_PR_gTPTunnel;
/* dLQosFlowPerTNLInformation */
pdusessionTransfer_p = (NGAP_PDUSessionResourceSetupResponseTransfer_t *)calloc(1, sizeof(NGAP_PDUSessionResourceSetupResponseTransfer_t));
pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.present = NGAP_UPTransportLayerInformation_PR_gTPTunnel;
GTP_TEID_TO_ASN1(initial_ctxt_resp_p->pdusessions[i].gtp_teid, &pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->gTP_TEID);
GTP_TEID_TO_ASN1(initial_ctxt_resp_p->pdusessions[i].gtp_teid, &pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->gTP_TEID);
pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress.buf = malloc(initial_ctxt_resp_p->pdusessions[i].gNB_addr.length);
pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress.buf = malloc(initial_ctxt_resp_p->pdusessions[i].gNB_addr.length);
memcpy(pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress.buf,
initial_ctxt_resp_p->pdusessions[i].gNB_addr.buffer,
initial_ctxt_resp_p->pdusessions[i].gNB_addr.length);
pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress.size = initial_ctxt_resp_p->pdusessions[i].gNB_addr.length;
pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress.bits_unused = 0;
memcpy(pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress.buf,
initial_ctxt_resp_p->pdusessions[i].gNB_addr.buffer,
initial_ctxt_resp_p->pdusessions[i].gNB_addr.length);
pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress.size = initial_ctxt_resp_p->pdusessions[i].gNB_addr.length;
pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress.bits_unused = 0;
NGAP_DEBUG("initial_ctxt_resp_p: pdusession ID %ld, gnb_addr %d.%d.%d.%d, SIZE %ld \n",
item->pDUSessionID,
pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress.buf[0],
pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress.buf[1],
pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress.buf[2],
pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress.buf[3],
pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress.size);
NGAP_DEBUG("initial_ctxt_resp_p: pdusession ID %ld, gnb_addr %d.%d.%d.%d, SIZE %ld \n",
item->pDUSessionID,
pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress.buf[0],
pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress.buf[1],
pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress.buf[2],
pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress.buf[3],
pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress.size);
/* associatedQosFlowList. number of 1? */
for(int j=0; j < initial_ctxt_resp_p->pdusessions[i].nb_of_qos_flow; j++) {
NGAP_AssociatedQosFlowItem_t *ass_qos_item_p;
ass_qos_item_p = (NGAP_AssociatedQosFlowItem_t *)calloc(1, sizeof(NGAP_AssociatedQosFlowItem_t));
/* associatedQosFlowList. number of 1? */
for(int j=0; j < initial_ctxt_resp_p->pdusessions[i].nb_of_qos_flow; j++) {
NGAP_AssociatedQosFlowItem_t *ass_qos_item_p;
ass_qos_item_p = (NGAP_AssociatedQosFlowItem_t *)calloc(1, sizeof(NGAP_AssociatedQosFlowItem_t));
/* qosFlowIdentifier */
ass_qos_item_p->qosFlowIdentifier = initial_ctxt_resp_p->pdusessions[i].associated_qos_flows[j].qci;
/* qosFlowIdentifier */
ass_qos_item_p->qosFlowIdentifier = initial_ctxt_resp_p->pdusessions[i].associated_qos_flows[j].qfi;
/* qosFlowMappingIndication */
if(initial_ctxt_resp_p->pdusessions[i].associated_qos_flows[j].qos_flow_mapping_ind != QOSFLOW_MAPPING_INDICATION_NON) {
ass_qos_item_p->qosFlowMappingIndication = malloc(sizeof(*ass_qos_item_p->qosFlowMappingIndication));
*ass_qos_item_p->qosFlowMappingIndication = initial_ctxt_resp_p->pdusessions[i].associated_qos_flows[j].qos_flow_mapping_ind;
/* qosFlowMappingIndication */
if(initial_ctxt_resp_p->pdusessions[i].associated_qos_flows[j].qos_flow_mapping_ind != QOSFLOW_MAPPING_INDICATION_NON) {
ass_qos_item_p->qosFlowMappingIndication = malloc(sizeof(*ass_qos_item_p->qosFlowMappingIndication));
*ass_qos_item_p->qosFlowMappingIndication = initial_ctxt_resp_p->pdusessions[i].associated_qos_flows[j].qos_flow_mapping_ind;
}
ASN_SEQUENCE_ADD(&pdusessionTransfer_p->dLQosFlowPerTNLInformation.associatedQosFlowList.list, ass_qos_item_p);
}
ASN_SEQUENCE_ADD(&pdusessionTransfer_p->dLQosFlowPerTNLInformation.associatedQosFlowList.list, ass_qos_item_p);
}
memset(&res, 0, sizeof(res));
res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, &asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, pdusessionTransfer_p);
item->pDUSessionResourceSetupResponseTransfer.buf = res.buffer;
item->pDUSessionResourceSetupResponseTransfer.size = res.result.encoded;
memset(&res, 0, sizeof(res));
res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, &asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, pdusessionTransfer_p);
item->pDUSessionResourceSetupResponseTransfer.buf = res.buffer;
item->pDUSessionResourceSetupResponseTransfer.size = res.result.encoded;
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, pdusessionTransfer_p);
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, pdusessionTransfer_p);
ASN_SEQUENCE_ADD(&ie->value.choice.PDUSessionResourceSetupListCxtRes.list, item);
ASN_SEQUENCE_ADD(&ie->value.choice.PDUSessionResourceSetupListCxtRes.list, item);
}
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
}
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
/* optional */
if (initial_ctxt_resp_p->nb_of_pdusessions_failed) {
ie = (NGAP_InitialContextSetupResponseIEs_t *)calloc(1, sizeof(NGAP_InitialContextSetupResponseIEs_t));
@@ -903,6 +907,7 @@ int ngap_gNB_ue_capabilities(instance_t instance,
/* Prepare the NGAP message to encode */
memset(&pdu, 0, sizeof(pdu));
pdu.present = NGAP_NGAP_PDU_PR_initiatingMessage;
pdu.choice.initiatingMessage = (NGAP_InitiatingMessage_t *)calloc(1,sizeof(NGAP_InitiatingMessage_t));
pdu.choice.initiatingMessage->procedureCode = NGAP_ProcedureCode_id_UERadioCapabilityInfoIndication;
pdu.choice.initiatingMessage->criticality = NGAP_Criticality_ignore;
pdu.choice.initiatingMessage->value.present = NGAP_InitiatingMessage__value_PR_UERadioCapabilityInfoIndication;
@@ -996,6 +1001,7 @@ int ngap_gNB_pdusession_setup_resp(instance_t instance,
/* Prepare the NGAP message to encode */
memset(&pdu, 0, sizeof(pdu));
pdu.present = NGAP_NGAP_PDU_PR_successfulOutcome;
pdu.choice.successfulOutcome = (NGAP_SuccessfulOutcome_t *)calloc(1,sizeof(struct NGAP_SuccessfulOutcome));
pdu.choice.successfulOutcome->procedureCode = NGAP_ProcedureCode_id_PDUSessionResourceSetup;
pdu.choice.successfulOutcome->criticality = NGAP_Criticality_reject;
pdu.choice.successfulOutcome->value.present = NGAP_SuccessfulOutcome__value_PR_PDUSessionResourceSetupResponse;
@@ -1036,6 +1042,8 @@ int ngap_gNB_pdusession_setup_resp(instance_t instance,
pdusessionTransfer_p = (NGAP_PDUSessionResourceSetupResponseTransfer_t *)calloc(1, sizeof(NGAP_PDUSessionResourceSetupResponseTransfer_t));
pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.present = NGAP_UPTransportLayerInformation_PR_gTPTunnel;
pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel =
calloc(1, sizeof(struct NGAP_GTPTunnel));
GTP_TEID_TO_ASN1(pdusession_setup_resp_p->pdusessions[i].gtp_teid, &pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->gTP_TEID);
@@ -1061,20 +1069,28 @@ int ngap_gNB_pdusession_setup_resp(instance_t instance,
ass_qos_item_p = (NGAP_AssociatedQosFlowItem_t *)calloc(1, sizeof(NGAP_AssociatedQosFlowItem_t));
/* qosFlowIdentifier */
ass_qos_item_p->qosFlowIdentifier = pdusession_setup_resp_p->pdusessions[i].associated_qos_flows[j].qci;
ass_qos_item_p->qosFlowIdentifier = pdusession_setup_resp_p->pdusessions[i].associated_qos_flows[j].qfi;
/* qosFlowMappingIndication */
if(pdusession_setup_resp_p->pdusessions[i].associated_qos_flows[j].qos_flow_mapping_ind != QOSFLOW_MAPPING_INDICATION_NON) {
ass_qos_item_p->qosFlowMappingIndication = malloc(sizeof(*ass_qos_item_p->qosFlowMappingIndication));
*ass_qos_item_p->qosFlowMappingIndication = pdusession_setup_resp_p->pdusessions[i].associated_qos_flows[j].qos_flow_mapping_ind;
}
//if(pdusession_setup_resp_p->pdusessions[i].associated_qos_flows[j].qos_flow_mapping_ind != QOSFLOW_MAPPING_INDICATION_NON) {
// ass_qos_item_p->qosFlowMappingIndication = malloc(sizeof(*ass_qos_item_p->qosFlowMappingIndication));
// *ass_qos_item_p->qosFlowMappingIndication = pdusession_setup_resp_p->pdusessions[i].associated_qos_flows[j].qos_flow_mapping_ind;
//}
ASN_SEQUENCE_ADD(&pdusessionTransfer_p->dLQosFlowPerTNLInformation.associatedQosFlowList.list, ass_qos_item_p);
}
memset(&res, 0, sizeof(res));
res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, &asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, pdusessionTransfer_p);
item->pDUSessionResourceSetupResponseTransfer.buf = res.buffer;
item->pDUSessionResourceSetupResponseTransfer.size = res.result.encoded;
// res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, &asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, pdusessionTransfer_p);
// item->pDUSessionResourceSetupResponseTransfer.buf = res.buffer;
// item->pDUSessionResourceSetupResponseTransfer.size = res.result.encoded;
uint8_t buffer[100];
asn_enc_rval_t enc_rval = aper_encode_to_buffer(&asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer,
NULL,
pdusessionTransfer_p,
buffer,100);
AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded);
item->pDUSessionResourceSetupResponseTransfer.buf = buffer;
item->pDUSessionResourceSetupResponseTransfer.size = enc_rval.encoded;
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, pdusessionTransfer_p);
@@ -1218,6 +1234,7 @@ int ngap_gNB_pdusession_modify_resp(instance_t instance,
/* Prepare the NGAP message to encode */
memset(&pdu, 0, sizeof(pdu));
pdu.present = NGAP_NGAP_PDU_PR_successfulOutcome;
pdu.choice.successfulOutcome = (NGAP_SuccessfulOutcome_t *)calloc(1,sizeof(struct NGAP_SuccessfulOutcome));
pdu.choice.successfulOutcome->procedureCode = NGAP_ProcedureCode_id_PDUSessionResourceModify;
pdu.choice.successfulOutcome->criticality = NGAP_Criticality_reject;
pdu.choice.successfulOutcome->value.present = NGAP_SuccessfulOutcome__value_PR_PDUSessionResourceModifyResponse;
@@ -1378,6 +1395,7 @@ int ngap_gNB_pdusession_release_resp(instance_t instance,
/* Prepare the NGAP message to encode */
memset(&pdu, 0, sizeof(pdu));
pdu.present = NGAP_NGAP_PDU_PR_successfulOutcome;
pdu.choice.successfulOutcome = (NGAP_SuccessfulOutcome_t *)calloc(1,sizeof(struct NGAP_SuccessfulOutcome));
pdu.choice.successfulOutcome->procedureCode = NGAP_ProcedureCode_id_PDUSessionResourceRelease;
pdu.choice.successfulOutcome->criticality = NGAP_Criticality_reject;
pdu.choice.successfulOutcome->value.present = NGAP_SuccessfulOutcome__value_PR_PDUSessionResourceReleaseResponse;
+2 -2
View File
@@ -82,8 +82,8 @@ struct ngap_gNB_ue_context_s *ngap_gNB_get_ue_context(
memset(&temp, 0, sizeof(struct ngap_gNB_ue_context_s));
/* gNB ue ngap id = 24 bits wide */
temp.gNB_ue_ngap_id = gNB_ue_ngap_id & 0x00FFFFFF;
/* gNB ue ngap id = 32 bits wide */
temp.gNB_ue_ngap_id = gNB_ue_ngap_id & 0xFFFFFFFF;
return RB_FIND(ngap_ue_map, &instance_p->ngap_ue_head, &temp);
}