Files
openairinterface5g/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_lib.c
T
Guido Casati 31f1402790 Add common definitions to new fgmm_lib.c/.h files
The 5GMM library in openair3/NAS/NR_UE/5GS/5GMM/ contains the
all the definitions necessary to do the enc/dec of 5GMM IEs.
5GMM messages can share the same IEs, therefore they can use
common definitions and enc/dec functions.

The goal of this commit is to add common definitions to new shared
5GMM library files. The consumers of fgmm_lib are the functions
defined in the openair3/NAS/NR_UE/5GS/5GMM/ library.
2025-03-25 16:29:25 +01:00

153 lines
5.3 KiB
C

/*
* 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_lib.h"
#include <string.h>
#include <arpa/inet.h> // For htons and ntohs
#include <stdlib.h> // For malloc and free
#include "common/utils/ds/byte_array.h"
#define GPRS_TIMER_LENGTH 3 // octets
/**
* Encode PDU Session Status and PDU session reactivation result (optional IEs)
* According to 9.11.3.42 and 9.11.3.44 of 3GPP TS 24.501, both IEs share the same
* structure, therefore this function covers them both.
* @param iei IE identifier to distinguish between PDU Session Status and PDU session reactivation result.
* @param psi pointer to PDU Session Status IE buffer to be encoded: index i corresponds to PDU Session i
*/
int encode_pdu_session_ie(byte_array_t *buffer, nas_service_IEI_t iei, const uint8_t *psi)
{
if (buffer->len < MIN_PDU_SESSION_CONTENTS_LEN + 2) {
PRINT_NAS_ERROR("%s failed: buffer is too small", __func__);
return -1;
}
uint8_t *buf = buffer->buf;
int encoded = 0;
buf[encoded++] = iei;
buf[encoded++] = MIN_PDU_SESSION_CONTENTS_LEN; // no spare octets
// Initialize the PDU session status octets to zero
buf[encoded] = 0x00;
buf[encoded + 1] = 0x00;
/* Encode Octet 3 (PSI 1-7) and Octet 4 (PSI 8-15).
Set each PSI bit according to the psi array containing the content IEs.
Start from bit 1 of octet 3 (i.e. PSI(0)), which is spare and shall be coded as zero.
The enabled bit translates to either PDU Session Active or PDU Session Reactivation Result */
for (int i = 1; i < 8; i++) { // skip spare bit
buf[encoded] |= psi[i] << i;
}
encoded++;
for (int i = 8; i < MAX_NUM_PSI; i++) {
buf[encoded] |= psi[i] << i % 8;
}
encoded++;
return encoded;
}
/**
* Decode PDU Session Status and PDU session reactivation result (optional IEs)
* According to 9.11.3.42 and 9.11.3.44 of 3GPP TS 24.501, both IEs share the same
* structure, therefore this function covers them both.
* @param psi pointer to buffer for the PDU Session Status IE to be decoded
*/
int decode_pdu_session_ie(uint8_t *psi, const byte_array_t *buffer)
{
int decoded = 0;
uint8_t *buf = buffer->buf;
if (buffer->len < MIN_PDU_SESSION_CONTENTS_LEN + 2) {
PRINT_NAS_ERROR("%s failed: buffer length is too small", __func__);
return -1;
}
// start decoding from length IE (IEI is decoded in the caller)
uint8_t pdu_session_status_len = buf[decoded++];
if (pdu_session_status_len > MAX_PDU_SESSION_CONTENTS_LEN) {
PRINT_NAS_ERROR("decoded length is out of bound for PDU Session Status/Reactivation result\n");
return -1;
}
/* Decode PDU Session Status content IEs bits in octet 3 (PSI 1-7).
Store the result psi array.
Skip bit 1 of octet 3 (i.e. PSI(0)), which is spare and shall be coded as zero. */
for (int i = 1; i < 8; i++) { // skip spare bit
psi[i] = (buf[decoded] >> i) & 0x01;
}
decoded++;
/* Decode PDU Session Status content IEs bits in octet 4 (PSI 8-15).
Store the result psi array. */
for (int i = 8; i < MAX_NUM_PSI; i++) {
psi[i] = (buf[decoded] >> i % 8) & 0x01;
}
decoded++;
return decoded;
}
/* Encode GPRS Timer IE (3GPP TS 24.008 10.5.7.3) */
int encode_gprs_timer_ie(byte_array_t *buffer, nas_service_IEI_t iei, const gprs_timer_t *timer)
{
if (buffer->len < GPRS_TIMER_LENGTH) {
PRINT_NAS_ERROR("Buffer length is too short to encode the GPRS Timer IE\n");
return -1;
}
uint8_t *buf = buffer->buf;
int encoded = 0;
// IEI
buf[encoded++] = iei;
// length
buf[encoded++] = 1; // length field (1 octet)
// Unit and value (1 octet)
uint8_t encoded_byte = 0;
encoded_byte |= (timer->unit & 0x07) << 5;
encoded_byte |= timer->value & 0x1F;
buf[encoded++] = encoded_byte;
return encoded;
}
/* Decode GPRS Timer IE (3GPP TS 24.008 10.5.7.3) */
int decode_gprs_timer_ie(gprs_timer_t *timer, const byte_array_t *buffer)
{
int decoded = 1; // Skip length ie (1 octet)
// Extract unit and value
uint8_t *buf = buffer->buf;
timer->unit = (buf[decoded] >> 5) & 0x07;
timer->value = buf[decoded++] & 0x1F;
return decoded;
}
/* Decode EAP Message (todo) */
int decode_eap_msg_ie(const byte_array_t *buffer)
{
int eap_msg_len = (buffer->buf[0] << 8) | buffer->buf[1];
PRINT_NAS_ERROR("EAP message IE in NAS Service Reject is not handled\n");
return eap_msg_len + 2; // content length + 2 octets for the length IE
}