Commit 384659ed authored by Guido Casati's avatar Guido Casati

Refactor capture_pdu_session_establishment_accept_msg

* the goal of this commit is to refactor capture_pdu_session_establishment_accept_msg
  into a decoding function
* PduSessionEstablishmentAccept.c is in the 5GSM library and shall only do encoding operations
* handling of PDU Session Establishment accept message is done in nr_nas_msg.c
* adopted new NAS decoding functions in the process
* improved QoS rules decoding
* convert getShort into a macro and add to NAS utils
parent 2e651ed2
......@@ -3,8 +3,4 @@ add_library(fgs_5gsm_lib OBJECT PduSessionEstablishRequest.c
target_link_libraries(fgs_5gsm_lib PUBLIC nas_common_ies_lib)
target_include_directories(fgs_5gsm_lib PUBLIC .
../../5GMM/MSG # NOTE: to be removed in a later commit
../../5GMM/IES # NOTE: to be removed in a later commit
../../
)
target_include_directories(fgs_5gsm_lib PUBLIC . ../../)
......@@ -23,8 +23,8 @@
#define PDU_SESSION_ESTABLISHMENT_ACCEPT_H_
#include <stdint.h>
#include <stdbool.h>
#include "fgs_nas_utils.h"
#include "NR_NAS_defs.h" // TEMP: to be removed in later commit
/* PDU Session Establish Accept Optional IE Identifiers - TS 24.501 Table 8.3.2.1.1 */
......@@ -79,6 +79,8 @@ typedef enum { FOREACH_IEI(TO_ENUM) } pduSessionEstablishment_IEI_t;
#define APN_MAX_LEN 100
#define APN_MIN_LEN 1
#define MAX_NUM_QOS_RULES 64
/* Mandatory Presence IE - TS 24.501 Table 8.3.2.1.1 */
typedef struct packet_filter_create_qos_rule_s {
......@@ -99,17 +101,26 @@ typedef struct packet_filter_s {
} packet_filter_t;
typedef struct qos_rule_s {
uint8_t id; /* QoS rule identifier */
uint16_t length; /* Length of QoS Rule */
uint8_t oc; /* Rule operation code (3bits) */
uint8_t dqr; /* DQR bit (1 bit) */
uint8_t nb_pf; /* Number of packet filters (4 bits) */
uint8_t prcd; /* QoS rule precedence */
uint8_t qfi; /* QoS Flow Identifier */
// QoS rule identifier
uint8_t id;
// Length of QoS Rule
uint16_t length;
// Rule operation code
uint8_t oc;
// Default QoS Rule
bool dqr;
// Number of packet filters
uint8_t nb_pf;
// QoS rule precedence
uint8_t precendence;
// QoS Flow Identifier
uint8_t qfi;
} qos_rule_t;
typedef struct auth_qos_rules_s {
uint16_t length; /* Length of QoS rules IE */
// QoS rules (M)
qos_rule_t rule[MAX_NUM_QOS_RULES];
} auth_qos_rule_t; /* QoS Rule as defined in 24.501 Figure 9.11.4.13.2 */
typedef struct session_ambr_s {
......@@ -147,20 +158,24 @@ typedef struct qos_fd_s {
} qos_fd_t; /* TS 24.501 9.11.4.12 - Ommited, only length is processed*/
typedef struct pdu_session_establishment_accept_msg_s {
/* Mandatory presence */
fgsm_msg_header_t header;
uint8_t pdu_type; /* PDU Session Type */
uint8_t ssc_mode; /* SSC mode */
auth_qos_rule_t qos_rules; /* Authorized QoS rules */
session_ambr_t sess_ambr; /* Session-AMBR */
/* Optional presence */
dnn_t dnn_ie; /* Data Network Name */
pdu_address_t pdu_addr_ie; /* PDU Address */
ext_pP_t ext_pp_ie; /* Extended Protocol Configuration Options */
qos_fd_t qos_fd_ie; /* QoS flow descriptions */
// PDU Session Type (M)
uint8_t pdu_type;
// Selected SSC Mode (M)
uint8_t ssc_mode;
// Authorized QoS rules (M)
auth_qos_rule_t qos_rules;
// Session-AMBR (M)
session_ambr_t sess_ambr;
// Data Network Name (O)
dnn_t dnn_ie;
// PDU Address (O)
pdu_address_t pdu_addr_ie;
// Extended Protocol Configuration Options (O)
ext_pP_t ext_pp_ie;
// QoS flow descriptions (O)
qos_fd_t qos_fd_ie;
} pdu_session_establishment_accept_msg_t; /* 24.501 Table 8.3.2.1.1 */
void capture_pdu_session_establishment_accept_msg(uint8_t *buffer, uint32_t msg_length);
int decode_pdu_session_establishment_accept_msg(pdu_session_establishment_accept_msg_t *psea_msg, uint8_t *buffer, uint32_t msg_length);
#endif
......@@ -23,6 +23,8 @@
#define FGS_NAS_UTILS_H
#include <stdint.h>
#include <arpa/inet.h>
#include <string.h> // For memcpy
#define PRINT_NAS_ERROR(...) fprintf(stderr, ##__VA_ARGS__)
......@@ -51,4 +53,10 @@ typedef struct {
#define TO_TEXT(LabEl, nUmID) {nUmID, #LabEl},
#define TO_ENUM(LabEl, nUmID ) LabEl = nUmID,
#define GET_SHORT(input, size) ({ \
uint16_t tmp16; \
memcpy(&tmp16, (input), sizeof(tmp16)); \
size += htons(tmp16); \
})
#endif // FGS_NAS_UTILS_H
......@@ -62,6 +62,8 @@
#include "openair3/UTILS/conversions.h"
#include "secu_defs.h"
#include "utils.h"
#include "openair2/SDAP/nr_sdap/nr_sdap.h"
#include "fgs_nas_utils.h"
#define MAX_NAS_UE 4
......@@ -815,6 +817,121 @@ static void generateRegistrationComplete(nr_ue_nas_t *nas,
}
}
/**
* @brief Capture IPv4 PDU Session Address
*/
static int capture_ipv4_addr(const uint8_t *addr, char *ip, size_t len)
{
return snprintf(ip, len, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
}
/**
* @brief Capture IPv6 PDU Session Address
*/
static int capture_ipv6_addr(const uint8_t *addr, char *ip, size_t len)
{
// 24.501 Sec 9.11.4.10: "an interface identifier for the IPv6 link local
// address": link local starts with fe80::, and only the last 64bits are
// given (middle is zero)
return snprintf(ip,
len,
"fe80::%02x%02x:%02x%02x:%02x%02x:%02x%02x",
addr[0],
addr[1],
addr[2],
addr[3],
addr[4],
addr[5],
addr[6],
addr[7]);
}
/**
* @brief Process PDU Session Address in PDU Session Establishment Accept message
* and configure the tun interface
*/
static void process_pdu_session_addr(pdu_session_establishment_accept_msg_t *msg)
{
uint8_t *addr = msg->pdu_addr_ie.pdu_addr_oct;
switch (msg->pdu_addr_ie.pdu_type) {
case PDU_SESSION_TYPE_IPV4: {
char ip[20];
capture_ipv4_addr(&addr[0], ip, sizeof(ip));
tun_config(1, ip, NULL, "oaitun_ue");
setup_ue_ipv4_route(1, ip, "oaitun_ue");
} break;
case PDU_SESSION_TYPE_IPV6: {
char ipv6[40];
capture_ipv6_addr(addr, ipv6, sizeof(ipv6));
tun_config(1, NULL, ipv6, "oaitun_ue");
} break;
case PDU_SESSION_TYPE_IPV4V6: {
char ipv6[40];
capture_ipv6_addr(addr, ipv6, sizeof(ipv6));
char ipv4[20];
capture_ipv4_addr(&addr[IPv6_INTERFACE_ID_LENGTH], ipv4, sizeof(ipv4));
tun_config(1, ipv4, ipv6, "oaitun_ue");
setup_ue_ipv4_route(1, ipv4, "oaitun_ue");
} break;
default:
LOG_E(NAS, "Unknown PDU Session Address type %d\n", msg->pdu_addr_ie.pdu_type);
break;
}
}
/**
* @brief Handle PDU Session Establishment Accept and process decoded message
*/
static void handle_pdu_session_accept(uint8_t *pdu_buffer, uint32_t msg_length)
{
pdu_session_establishment_accept_msg_t msg = {0};
int size = 0;
int decoded = 0;
// Security protected NAS header (7 bytes)
fgs_nas_message_security_header_t sec_nas_hdr = {0};
if ((decoded = decode_5gs_security_protected_header(&sec_nas_hdr, pdu_buffer, msg_length)) < 0) {
LOG_E(NAS, "decode_5gs_security_protected_header failure in PDU Session Establishment Accept decoding\n");
return;
}
size += decoded;
// decode plain 5GMM message header
fgmm_msg_header_t mm_header = {0};
if ((decoded = decode_5gmm_msg_header(&mm_header, pdu_buffer + size, msg_length - size)) < 0) {
LOG_E(NAS, "decode_5gmm_msg_header failure in PDU Session Establishment Accept decoding\n");
return;
}
size += decoded;
/* Process container (5GSM message) */
// Payload container type and spare (1 octet)
size++;
// Payload container length
uint16_t iei_len = 0;
GET_SHORT(pdu_buffer + size, iei_len);
size += sizeof(iei_len);
// decode plain 5GSM message header
fgsm_msg_header_t sm_header = {0};
if ((decoded = decode_5gsm_msg_header(&sm_header, pdu_buffer + size, msg_length - size)) < 0) {
LOG_E(NAS, "decode_5gsm_msg_header failure in PDU Session Establishment Accept decoding\n");
return;
}
size += decoded;
// decode PDU Session Establishment Accept
if (!decode_pdu_session_establishment_accept_msg(&msg, pdu_buffer + size, msg_length))
LOG_E(NAS, "decode_pdu_session_establishment_accept_msg failure\n");
// process PDU Session
process_pdu_session_addr(&msg);
set_qfi_pduid(msg.qos_rules.rule->qfi, sm_header.pdu_session_id);
}
/**
* @brief Handle DL NAS Transport and process piggybacked 5GSM messages
*/
......@@ -823,7 +940,7 @@ static void handleDownlinkNASTransport(uint8_t *pdu_buffer, uint32_t msg_length)
uint8_t msg_type = *(pdu_buffer + 16);
if (msg_type == FGS_PDU_SESSION_ESTABLISHMENT_ACC) {
LOG_A(NAS, "Received PDU Session Establishment Accept in DL NAS Transport\n");
capture_pdu_session_establishment_accept_msg(pdu_buffer, msg_length);
handle_pdu_session_accept(pdu_buffer, msg_length);
} else {
LOG_E(NAS, "Received unexpected message in DLinformationTransfer %d\n", msg_type);
}
......@@ -1281,7 +1398,7 @@ void *nas_nrue(void *args_p)
if (msg_type == FGS_REGISTRATION_ACCEPT) {
handle_registration_accept(nas, pdu_buffer, pdu_length);
} else if (msg_type == FGS_PDU_SESSION_ESTABLISHMENT_ACC) {
capture_pdu_session_establishment_accept_msg(pdu_buffer, pdu_length);
handle_pdu_session_accept(pdu_buffer, pdu_length);
}
// Free NAS buffer memory after use (coming from RRC)
......@@ -1378,7 +1495,7 @@ void *nas_nrue(void *args_p)
LOG_I(NAS, "received deregistration accept\n");
break;
case FGS_PDU_SESSION_ESTABLISHMENT_ACC:
capture_pdu_session_establishment_accept_msg(pdu_buffer, pdu_length);
handle_pdu_session_accept(pdu_buffer, pdu_length);
break;
case FGS_PDU_SESSION_ESTABLISHMENT_REJ:
LOG_E(NAS, "Received PDU Session Establishment reject\n");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment