From 384659ed54bfeb79a692b306910402a8d307e318 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 11 Dec 2024 12:50:54 +0100 Subject: [PATCH] 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 --- .../NAS/NR_UE/5GS/5GSM/MSG/CMakeLists.txt | 6 +- .../5GSM/MSG/PduSessionEstablishmentAccept.c | 202 ++++++++---------- .../5GSM/MSG/PduSessionEstablishmentAccept.h | 57 +++-- openair3/NAS/NR_UE/5GS/fgs_nas_utils.h | 8 + openair3/NAS/NR_UE/nr_nas_msg.c | 123 ++++++++++- 5 files changed, 254 insertions(+), 142 deletions(-) diff --git a/openair3/NAS/NR_UE/5GS/5GSM/MSG/CMakeLists.txt b/openair3/NAS/NR_UE/5GS/5GSM/MSG/CMakeLists.txt index ca115451b3..1630a48222 100644 --- a/openair3/NAS/NR_UE/5GS/5GSM/MSG/CMakeLists.txt +++ b/openair3/NAS/NR_UE/5GS/5GSM/MSG/CMakeLists.txt @@ -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 . ../../) diff --git a/openair3/NAS/NR_UE/5GS/5GSM/MSG/PduSessionEstablishmentAccept.c b/openair3/NAS/NR_UE/5GS/5GSM/MSG/PduSessionEstablishmentAccept.c index 6a7c1f7211..50b66845c6 100644 --- a/openair3/NAS/NR_UE/5GS/5GSM/MSG/PduSessionEstablishmentAccept.c +++ b/openair3/NAS/NR_UE/5GS/5GSM/MSG/PduSessionEstablishmentAccept.c @@ -24,101 +24,83 @@ #include "PduSessionEstablishmentAccept.h" #include "common/utils/LOG/log.h" #include "common/utils/tun_if.h" -#include "NR_NAS_defs.h" +#include "fgs_nas_utils.h" -static uint16_t getShort(uint8_t *input) +/** + * @brief Returns the size of the single QoS rule IE + */ +static uint8_t get_len_qos_rule(qos_rule_t *rule) { - uint16_t tmp16; - memcpy(&tmp16, input, sizeof(tmp16)); - return htons(tmp16); + return rule->length + sizeof(rule->id) + sizeof(rule->length); } -static int capture_ipv4_addr(const uint8_t *addr, char *ip, size_t len) +/** + * @brief Decode QoS Rule (9.11.4.13 of 3GPP TS 24.501) + */ +static qos_rule_t decode_qos_rule(uint8_t *buf) { - return snprintf(ip, len, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); -} - -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]); + qos_rule_t qos_rule = {0}; + // octet 4 + qos_rule.id = *buf++; + // octet 5 - 6 + GET_SHORT(buf, qos_rule.length); + buf += sizeof(qos_rule.length); + // octet 7 + qos_rule.oc = (*(buf)&0xE0) >> 5; + qos_rule.dqr = (*(buf)&0x10) >> 4; + qos_rule.nb_pf = *buf++ & 0x0F; + // octet 8 - m + for (int i = 0; i < qos_rule.nb_pf; i++) { + packet_filter_t pf; + if (qos_rule.oc == ROC_CREATE_NEW_QOS_RULE || qos_rule.oc == ROC_MODIFY_QOS_RULE_ADD_PF + || qos_rule.oc == ROC_MODIFY_QOS_RULE_REPLACE_PF) { + pf.pf_type.type_1.pf_dir = (*buf & 0x30) >> 4; + pf.pf_type.type_1.pf_id = *buf++ & 0x0F; + pf.pf_type.type_1.length = *buf++; + buf += pf.pf_type.type_1.length; // skip PF content + } else if (qos_rule.oc == ROC_MODIFY_QOS_RULE_DELETE_PF) { + pf.pf_type.type_2.pf_id = *buf++; + } + } + // octet m + 1 + qos_rule.precendence = *buf++; + // octet m + 2 + qos_rule.qfi = *buf++ & 0x3F; + return qos_rule; } /** * @brief PDU session establishment accept (8.3.2 of 3GPP TS 24.501) * network to UE */ -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) { - fgs_nas_message_security_header_t sec_nas_hdr; - pdu_session_establishment_accept_msg_t psea_msg; uint8_t *curPtr = buffer; - // Security protected NAS header (7 bytes) - sec_nas_hdr.protocol_discriminator = *curPtr++; - sec_nas_hdr.security_header_type = *curPtr++; - uint32_t tmp; - memcpy(&tmp, buffer, sizeof(tmp)); - sec_nas_hdr.message_authentication_code = htonl(tmp); - curPtr += sizeof(sec_nas_hdr.message_authentication_code); - sec_nas_hdr.sequence_number = *curPtr++; - // Security protected plain NAS message - fgmm_msg_header_t header; - header.ex_protocol_discriminator = *curPtr++; - header.security_header_type = *curPtr++; - header.message_type = *curPtr++; - // Payload container type and spare (1 octet) - curPtr++; - // Payload container length - curPtr += sizeof(getShort(curPtr)); - /* Mandatory Presence IEs */ - fgsm_msg_header_t *sm_header = &psea_msg.header; - sm_header->ex_protocol_discriminator = *curPtr++; - sm_header->pdu_session_id = *curPtr++; - sm_header->pti = *curPtr++; - sm_header->message_type = *curPtr++; - psea_msg.pdu_type = *curPtr & 0x0f; - psea_msg.ssc_mode = (*curPtr++ & 0xf0) >> 4; - psea_msg.qos_rules.length = getShort(curPtr); - curPtr += sizeof(psea_msg.qos_rules.length); - /* Supports the capture of only one QoS Rule, it should be changed for multiple QoS Rules */ - qos_rule_t qos_rule; - qos_rule.id = *curPtr++; - qos_rule.length = getShort(curPtr); - curPtr += sizeof(qos_rule.length); - qos_rule.oc = (*(curPtr)&0xE0) >> 5; - qos_rule.dqr = (*(curPtr)&0x10) >> 4; - qos_rule.nb_pf = *curPtr++ & 0x0F; - if (qos_rule.nb_pf) { - packet_filter_t pf; - - if (qos_rule.oc == ROC_CREATE_NEW_QOS_RULE || qos_rule.oc == ROC_MODIFY_QOS_RULE_ADD_PF - || qos_rule.oc == ROC_MODIFY_QOS_RULE_REPLACE_PF) { - pf.pf_type.type_1.pf_dir = (*curPtr & 0x30) >> 4; - pf.pf_type.type_1.pf_id = *curPtr++ & 0x0F; - pf.pf_type.type_1.length = *curPtr++; - curPtr += (qos_rule.nb_pf * pf.pf_type.type_1.length); /* Ommit the Packet filter List */ - } else if (qos_rule.oc == ROC_MODIFY_QOS_RULE_DELETE_PF) { - curPtr += qos_rule.nb_pf; - } + /* Mandatory PDU Session Establishment Accept IEs */ + // PDU Session Type (half octet) + psea_msg->pdu_type = *curPtr & 0x0f; + // SSC Mode (half octet) + psea_msg->ssc_mode = (*curPtr++ & 0xf0) >> 4; + // Authorized QoS Rules + auth_qos_rule_t *qos_rules = &psea_msg->qos_rules; + // Length of the rule IEs (2 octets) + GET_SHORT(curPtr, qos_rules->length); + curPtr += sizeof(qos_rules->length); + /* Decode rule IEs as long as the total length + of all IEs (qos_rules->length) is not reached */ + uint16_t rules_tot_len = 0; + while (rules_tot_len < qos_rules->length) + { + qos_rules->rule[0] = decode_qos_rule(curPtr); + rules_tot_len += get_len_qos_rule(&qos_rules->rule[0]); + curPtr += rules_tot_len; } + // Session-AMBR (M) + psea_msg->sess_ambr.length = *curPtr++; + curPtr += psea_msg->sess_ambr.length; // skip content - qos_rule.prcd = *curPtr++; - qos_rule.qfi = *curPtr++; - psea_msg.sess_ambr.length = *curPtr++; - curPtr += psea_msg.sess_ambr.length; /* Ommit the Seassion-AMBR */ + uint8_t *resPtr = curPtr; /* Optional Presence IEs */ while (curPtr < buffer + msg_length) { @@ -130,11 +112,11 @@ void capture_pdu_session_establishment_accept_msg(uint8_t *buffer, uint32_t msg_ break; case IEI_PDU_ADDRESS: - psea_msg.pdu_addr_ie.pdu_length = *curPtr++; + psea_msg->pdu_addr_ie.pdu_length = *curPtr++; /* Octet 3 */ // PDU type (3 bits) - psea_msg.pdu_addr_ie.pdu_type = *curPtr & 0x07; + psea_msg->pdu_addr_ie.pdu_type = *curPtr & 0x07; // SMF's IPv6 link local address (1 bit) uint8_t si6lla = (*curPtr >> 3) & 0x01; if (si6lla) @@ -143,37 +125,29 @@ void capture_pdu_session_establishment_accept_msg(uint8_t *buffer, uint32_t msg_ /* Octet 4 to n */ // PDU address information - uint8_t *addr = psea_msg.pdu_addr_ie.pdu_addr_oct; - if (psea_msg.pdu_addr_ie.pdu_type == PDU_SESSION_TYPE_IPV4) { + uint8_t *addr = psea_msg->pdu_addr_ie.pdu_addr_oct; + if (psea_msg->pdu_addr_ie.pdu_type == PDU_SESSION_TYPE_IPV4) { for (int i = 0; i < IPv4_ADDRESS_LENGTH; ++i) addr[i] = *curPtr++; - 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"); - LOG_I(NAS, "Received PDU Session Establishment Accept, UE IP: %u.%u.%u.%u\n", addr[0], addr[1], addr[2], addr[3]); - } else if (psea_msg.pdu_addr_ie.pdu_type == PDU_SESSION_TYPE_IPV6) { + LOG_I(NAS, "Received PDU Session Establishment Accept, UE IPv4: %u.%u.%u.%u\n", addr[0], addr[1], addr[2], addr[3]); + } else if (psea_msg->pdu_addr_ie.pdu_type == PDU_SESSION_TYPE_IPV6) { for (int i = 0; i < IPv6_INTERFACE_ID_LENGTH; ++i) addr[i] = *curPtr++; - char ipv6[40]; - capture_ipv6_addr(addr, ipv6, sizeof(ipv6)); - tun_config(1, NULL, ipv6, "oaitun_ue"); - } else if (psea_msg.pdu_addr_ie.pdu_type == PDU_SESSION_TYPE_IPV4V6) { + LOG_I(NAS, "Received PDU Session Establishment Accept, UE IPv6: %u.%u.%u.%u.%u.%u.%u.%u\n", + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7]); + } else if (psea_msg->pdu_addr_ie.pdu_type == PDU_SESSION_TYPE_IPV4V6) { // 24.501 Sec 9.11.4.10: "If the PDU session type value indicates // IPv4v6, the PDU address information in octet 4 to octet 11 // contains an interface identifier for the IPv6 link local address // and in octet 12 to octet 15 contains an IPv4 address." for (int i = 0; i < IPv4_ADDRESS_LENGTH + IPv6_INTERFACE_ID_LENGTH; ++i) addr[i] = *curPtr++; - 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"); + LOG_I(NAS, "Received PDU Session Establishment Accept, UE IPv4v6: %u.%u.%u.%u/%u.%u.%u.%u.%u.%u.%u.%u\n", + addr[0], addr[1], addr[2], addr[3], + addr[4], addr[5], addr[6], addr[7], addr[8], addr[9], addr[10], addr[11]); } else { - LOG_E(NAS, "unknown/unhandled PDU session establishment accept PDU type %d\n", psea_msg.pdu_addr_ie.pdu_type); - curPtr += psea_msg.pdu_addr_ie.pdu_length; + LOG_E(NAS, "unknown/unhandled PDU session establishment accept PDU type %d\n", psea_msg->pdu_addr_ie.pdu_type); + curPtr += psea_msg->pdu_addr_ie.pdu_length; } break; @@ -192,48 +166,50 @@ void capture_pdu_session_establishment_accept_msg(uint8_t *buffer, uint32_t msg_ break; case IEI_MAPPED_EPS: { - uint16_t mapped_eps_length = getShort(curPtr); + uint16_t mapped_eps_length = 0; + GET_SHORT(curPtr, mapped_eps_length); curPtr += mapped_eps_length; break; } case IEI_EAP_MSG: { - uint16_t eap_length = getShort(curPtr); + uint16_t eap_length = 0; + GET_SHORT(curPtr, eap_length); curPtr += (eap_length + sizeof(eap_length)); break; } case IEI_AUTH_QOS_DESC: { - psea_msg.qos_fd_ie.length = getShort(curPtr); - curPtr += (psea_msg.qos_fd_ie.length + sizeof(psea_msg.qos_fd_ie.length)); + GET_SHORT(curPtr, psea_msg->qos_fd_ie.length); + curPtr += (psea_msg->qos_fd_ie.length + sizeof(psea_msg->qos_fd_ie.length)); break; } case IEI_EXT_CONF_OPT: { - psea_msg.ext_pp_ie.length = getShort(curPtr); - curPtr += (psea_msg.ext_pp_ie.length + sizeof(psea_msg.ext_pp_ie.length)); + GET_SHORT(curPtr, psea_msg->ext_pp_ie.length); + curPtr += (psea_msg->ext_pp_ie.length + sizeof(psea_msg->ext_pp_ie.length)); break; } case IEI_DNN: { - psea_msg.dnn_ie.dnn_length = *curPtr++; + psea_msg->dnn_ie.dnn_length = *curPtr++; char apn[APN_MAX_LEN]; - if (psea_msg.dnn_ie.dnn_length <= APN_MAX_LEN && psea_msg.dnn_ie.dnn_length >= APN_MIN_LEN) { - memcpy(apn, curPtr, psea_msg.dnn_ie.dnn_length); + if (psea_msg->dnn_ie.dnn_length <= APN_MAX_LEN && psea_msg->dnn_ie.dnn_length >= APN_MIN_LEN) { + memcpy(apn, curPtr, psea_msg->dnn_ie.dnn_length); LOG_T(NAS, "PDU SESSION ESTABLISHMENT ACCEPT - APN: %s\n", apn); } else LOG_E(NAS, "PDU SESSION ESTABLISHMENT ACCEPT - DNN IE has invalid length\n"); - + resPtr = curPtr; curPtr = buffer + msg_length; // we force stop processing break; } default: + PRINT_NAS_ERROR("Unknown IEI %d\n", psea_iei); curPtr = buffer + msg_length; // we force stop processing break; } } - - return; + return resPtr - buffer; } diff --git a/openair3/NAS/NR_UE/5GS/5GSM/MSG/PduSessionEstablishmentAccept.h b/openair3/NAS/NR_UE/5GS/5GSM/MSG/PduSessionEstablishmentAccept.h index 69c9cde844..80694814b4 100644 --- a/openair3/NAS/NR_UE/5GS/5GSM/MSG/PduSessionEstablishmentAccept.h +++ b/openair3/NAS/NR_UE/5GS/5GSM/MSG/PduSessionEstablishmentAccept.h @@ -23,8 +23,8 @@ #define PDU_SESSION_ESTABLISHMENT_ACCEPT_H_ #include +#include #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 diff --git a/openair3/NAS/NR_UE/5GS/fgs_nas_utils.h b/openair3/NAS/NR_UE/5GS/fgs_nas_utils.h index 3082bc7daa..09754e9903 100644 --- a/openair3/NAS/NR_UE/5GS/fgs_nas_utils.h +++ b/openair3/NAS/NR_UE/5GS/fgs_nas_utils.h @@ -23,6 +23,8 @@ #define FGS_NAS_UTILS_H #include +#include +#include // 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 diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index 204c3733ec..bfb3b73ea6 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -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");