From 5af4b8920303eecc14f8a3877453858feb5eeeb2 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 15 Nov 2024 19:16:51 +0100 Subject: [PATCH] Add enc/dec function for NAS Service Reject library --- .../NAS/NR_UE/5GS/5GMM/MSG/CMakeLists.txt | 1 + .../NR_UE/5GS/5GMM/MSG/fgmm_service_reject.c | 154 ++++++++++++++++++ .../NR_UE/5GS/5GMM/MSG/fgmm_service_reject.h | 45 +++++ 3 files changed, 200 insertions(+) create mode 100644 openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_service_reject.c create mode 100644 openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_service_reject.h diff --git a/openair3/NAS/NR_UE/5GS/5GMM/MSG/CMakeLists.txt b/openair3/NAS/NR_UE/5GS/5GMM/MSG/CMakeLists.txt index 6947a3421c..c1a28a18f3 100644 --- a/openair3/NAS/NR_UE/5GS/5GMM/MSG/CMakeLists.txt +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/CMakeLists.txt @@ -2,6 +2,7 @@ add_library(fgs_5gmm_lib OBJECT fgmm_lib.c fgs_service_request.c fgmm_service_accept.c + fgmm_service_reject.c RegistrationRequest.c RegistrationAccept.c FGSIdentityResponse.c diff --git a/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_service_reject.c b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_service_reject.c new file mode 100644 index 0000000000..74175fda36 --- /dev/null +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_service_reject.c @@ -0,0 +1,154 @@ +/* + * 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 + */ + +#include "fgmm_service_reject.h" +#include +#include // For htons and ntohs +#include // For malloc and free +#include "common/utils/ds/byte_array.h" +#include "common/utils/utils.h" +#include "fgmm_lib.h" + +#define SERVICE_REJECT_MIN_LEN 1 // 1 octet + +/** @brief Encode Service Reject (8.2.18 of 3GPP TS 24.501) */ +int encode_fgs_service_reject(byte_array_t *buffer, const fgs_service_reject_msg_t *msg) +{ + if (buffer->len < SERVICE_REJECT_MIN_LEN) { + PRINT_NAS_ERROR("Failed to encode Service Reject: missing Cause IE!\n"); + return -1; + } + + byte_array_t ba = *buffer; // Local copy of buffer + int encoded = 0; + + // 5GMM cause (Mandatory) + buffer->buf[encoded++] = msg->cause; + UPDATE_BYTE_ARRAY(ba, 1); + + // PDU Session Status (Optional) + if (msg->has_psi_status) { + ENCODE_NAS_IE(ba, encode_pdu_session_ie(&ba, IEI_PDU_SESSION_STATUS, msg->psi_status), encoded); + } + + // T3446 Timer (Optional) + if (msg->t3446) { + ENCODE_NAS_IE(ba, encode_gprs_timer_ie(&ba, IEI_T3446_VALUE, msg->t3446), encoded); + } + + // T3448 Timer (Optional) + if (msg->t3448) { + ENCODE_NAS_IE(ba, encode_gprs_timer_ie(&ba, IEI_T3448_VALUE, msg->t3448), encoded); + } + + return encoded; +} + +/** @brief Decode Service Reject (8.2.18 of 3GPP TS 24.501) */ +int decode_fgs_service_reject(fgs_service_reject_msg_t *msg, const byte_array_t *buffer) +{ + if (buffer->len < SERVICE_REJECT_MIN_LEN) { + PRINT_NAS_ERROR("Nothing to decode: missing Cause IE!\n"); + return -1; + } + + byte_array_t ba = *buffer; // Local copy of buffer to be used in the decoding sub-functions + uint32_t decoded = 0; + + // Cause (Mandatory) + msg->cause = buffer->buf[decoded++]; + UPDATE_BYTE_ARRAY(ba, 1); + + // Decode Optional IEs + while (decoded < buffer->len) { + uint8_t iei = buffer->buf[decoded++]; + UPDATE_BYTE_ARRAY(ba, 1); // Skip IEI + + switch (iei) { + case IEI_PDU_SESSION_STATUS: + msg->has_psi_status = true; + DECODE_NAS_IE(ba, decode_pdu_session_ie(msg->psi_status, &ba), decoded); + break; + + case IEI_T3448_VALUE: + msg->t3448 = malloc_or_fail(sizeof(*msg->t3448)); + DECODE_NAS_IE(ba, decode_gprs_timer_ie(msg->t3448, (const byte_array_t *)&ba), decoded); + break; + + case IEI_T3446_VALUE: + msg->t3446 = malloc_or_fail(sizeof(*msg->t3446)); + DECODE_NAS_IE(ba, decode_gprs_timer_ie(msg->t3446, (const byte_array_t *)&ba), decoded); + break; + + case IEI_EAPMSG: + DECODE_NAS_IE(ba, decode_eap_msg_ie((const byte_array_t *)&ba), decoded); + break; + + case IEI_CAG_INFO_LIST: { + int cag_list_len = (buffer->buf[decoded] << 8) | buffer->buf[decoded + 1]; + int cag_len = cag_list_len + 2; // encoded content + 2 octets for the length IE + decoded += cag_len; + UPDATE_BYTE_ARRAY(ba, cag_len); + PRINT_NAS_ERROR("CAG information list IE in NAS Service Reject is not handled\n"); + } break; + + default: + PRINT_NAS_ERROR("Uknown or invalid NAS Service Reject IEI %d\n", iei); + return -1; + } + } + + return decoded; +} + +/** @brief Equality check for Service Reject (enc/dec) */ +bool eq_service_reject(const fgs_service_reject_msg_t *a, const fgs_service_reject_msg_t *b) +{ + _NAS_EQ_CHECK_INT(a->cause, b->cause); + _NAS_EQ_CHECK_INT(a->has_psi_status, b->has_psi_status); + if (a->has_psi_status && b->has_psi_status) { + for (int i = 0; i < MAX_NUM_PSI; i++) + _NAS_EQ_CHECK_INT(a->psi_status[i], b->psi_status[i]); + } + if (a->t3448 != NULL || b->t3448 != NULL) { + if (a->t3448 == NULL || b->t3448 == NULL) { + PRINT_NAS_ERROR("t3448 equality check failed\n"); + return false; + } + if (!eq_gprs_timer(a->t3448, b->t3448)) + return false; + } + if (a->t3446 != NULL || b->t3446 != NULL) { + if (a->t3446 == NULL || b->t3446 == NULL) { + PRINT_NAS_ERROR("t3448 equality check failed\n"); + return false; + } + if (!eq_gprs_timer(a->t3446, b->t3446)) + return false; + } + return true; +} + +void free_fgs_service_reject(fgs_service_reject_msg_t *msg) +{ + free(msg->t3446); + free(msg->t3448); +} diff --git a/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_service_reject.h b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_service_reject.h new file mode 100644 index 0000000000..61337d8525 --- /dev/null +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_service_reject.h @@ -0,0 +1,45 @@ +/* + * 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 + */ + +#ifndef FGS_service_reject_H +#define FGS_service_reject_H + +#include +#include "fgmm_lib.h" + +typedef struct { + // 5GMM cause (Mandatory) + cause_id_t cause; + // T3346 Value (Optional) + gprs_timer_t *t3446; + // PDU Session Status (Optional) + uint8_t psi_status[MAX_NUM_PSI]; + bool has_psi_status; + // T3448 Value (Optional) + gprs_timer_t *t3448; +} fgs_service_reject_msg_t; + +int decode_fgs_service_reject(fgs_service_reject_msg_t *msg, const byte_array_t *buffer); +int encode_fgs_service_reject(byte_array_t *buffer, const fgs_service_reject_msg_t *msg); +void free_fgs_service_reject(fgs_service_reject_msg_t *msg); +bool eq_service_reject(const fgs_service_reject_msg_t *a, const fgs_service_reject_msg_t *b); + +#endif /* FGS_service_reject_H */