diff --git a/openair3/NAS/COMMON/ESM/MSG/PduSessionEstablishmentAccept.c b/openair3/NAS/COMMON/ESM/MSG/PduSessionEstablishmentAccept.c index a062fec68e..2872ba3d5e 100644 --- a/openair3/NAS/COMMON/ESM/MSG/PduSessionEstablishmentAccept.c +++ b/openair3/NAS/COMMON/ESM/MSG/PduSessionEstablishmentAccept.c @@ -124,18 +124,28 @@ void capture_pdu_session_establishment_accept_msg(uint8_t *buffer, uint32_t msg_ case IEI_PDU_ADDRESS: LOG_T(NAS, "PDU SESSION ESTABLISHMENT ACCEPT - Received PDU Address IE\n"); psea_msg.pdu_addr_ie.pdu_length = *curPtr++; - psea_msg.pdu_addr_ie.pdu_type = *curPtr++; + /* Octet 3 */ + // PDU type (3 bits) + 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) + LOG_E(NAS, "SMF's IPv6 link local address is not handled\n"); + curPtr++; + + /* 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) { - for (int i = 0; i < 4; ++i) + 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"); } else if (psea_msg.pdu_addr_ie.pdu_type == PDU_SESSION_TYPE_IPV6) { - for (int i = 0; i < 8; ++i) + for (int i = 0; i < IPv6_INTERFACE_ID_LENGTH; ++i) addr[i] = *curPtr++; char ipv6[40]; capture_ipv6_addr(addr, ipv6, sizeof(ipv6)); @@ -145,12 +155,12 @@ void capture_pdu_session_establishment_accept_msg(uint8_t *buffer, uint32_t msg_ // 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 < 12; ++i) + 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[8], ipv4, sizeof(ipv4)); + 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"); } else { @@ -164,42 +174,47 @@ void capture_pdu_session_establishment_accept_msg(uint8_t *buffer, uint32_t msg_ curPtr++; /* TS 24.008 10.5.7.3 */ break; - case IEI_SNSSAI: /* Ommited */ + case IEI_SNSSAI: { LOG_T(NAS, "PDU SESSION ESTABLISHMENT ACCEPT - Received S-NSSAI IE\n"); uint8_t snssai_length = *curPtr; curPtr += (snssai_length + sizeof(snssai_length)); break; + } case IEI_ALWAYSON_PDU: /* Ommited */ LOG_T(NAS, "PDU SESSION ESTABLISHMENT ACCEPT - Received Always-on PDU Session indication IE\n"); curPtr++; break; - case IEI_MAPPED_EPS: /* Ommited */ + case IEI_MAPPED_EPS: { LOG_T(NAS, "PDU SESSION ESTABLISHMENT ACCEPT - Received Mapped EPS bearer context IE\n"); uint16_t mapped_eps_length = getShort(curPtr); curPtr += mapped_eps_length; break; + } - case IEI_EAP_MSG: /* Ommited */ + case IEI_EAP_MSG: { LOG_T(NAS, "PDU SESSION ESTABLISHMENT ACCEPT - Received EAP message IE\n"); uint16_t eap_length = getShort(curPtr); curPtr += (eap_length + sizeof(eap_length)); break; + } - case IEI_AUTH_QOS_DESC: /* Ommited */ + case IEI_AUTH_QOS_DESC: { LOG_T(NAS, "PDU SESSION ESTABLISHMENT ACCEPT - Received Authorized QoS flow descriptions IE\n"); psea_msg.qos_fd_ie.length = getShort(curPtr); curPtr += (psea_msg.qos_fd_ie.length + sizeof(psea_msg.qos_fd_ie.length)); break; + } - case IEI_EXT_CONF_OPT: /* Ommited */ + case IEI_EXT_CONF_OPT: { LOG_T(NAS, "PDU SESSION ESTABLISHMENT ACCEPT - Received Extended protocol configuration options IE\n"); psea_msg.ext_pp_ie.length = getShort(curPtr); curPtr += (psea_msg.ext_pp_ie.length + sizeof(psea_msg.ext_pp_ie.length)); break; + } - case IEI_DNN: + case IEI_DNN: { LOG_T(NAS, "PDU SESSION ESTABLISHMENT ACCEPT - Received DNN IE\n"); psea_msg.dnn_ie.dnn_length = *curPtr++; char apn[APN_MAX_LEN]; @@ -213,6 +228,7 @@ void capture_pdu_session_establishment_accept_msg(uint8_t *buffer, uint32_t msg_ curPtr = buffer + msg_length; // we force stop processing break; + } default: LOG_T(NAS, "PDU SESSION ESTABLISHMENT ACCEPT - Not known IE\n"); diff --git a/openair3/NAS/COMMON/ESM/MSG/PduSessionEstablishmentAccept.h b/openair3/NAS/COMMON/ESM/MSG/PduSessionEstablishmentAccept.h index a254debfbe..c283079998 100644 --- a/openair3/NAS/COMMON/ESM/MSG/PduSessionEstablishmentAccept.h +++ b/openair3/NAS/COMMON/ESM/MSG/PduSessionEstablishmentAccept.h @@ -42,6 +42,9 @@ #define PDU_SESSION_TYPE_IPV4 0b001 #define PDU_SESSION_TYPE_IPV6 0b010 #define PDU_SESSION_TYPE_IPV4V6 0b011 +#define IPv4_ADDRESS_LENGTH 4 // length of the IPv4 address associated with a PDU session +#define IPv6_INTERFACE_ID_LENGTH 8 // interface identifier for the IPv6 link local address +#define SMF_IPv6_LLA_LENGTH 16 /* Rule operation codes - TS 24.501 Table 9.11.4.13.1 */ @@ -114,7 +117,8 @@ typedef struct pdu_address_s { uint8_t pdu_iei; /* PDU Address IEI (0x29) */ uint8_t pdu_length; /* Length of PDU address contents */ uint8_t pdu_type; /* PDU session type value */ - uint8_t pdu_addr_oct[12]; /* PDU address information (depending on type, up to 12 bytes)*/ + /// PDU address information (depending on type, up to 12 bytes) + uint8_t pdu_addr_oct[IPv4_ADDRESS_LENGTH + IPv6_INTERFACE_ID_LENGTH]; } pdu_address_t; /* TS 24.501 9.11.4.10 */ typedef struct dnn_s { diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index 98a87c7bfd..8d07ea8455 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -848,16 +848,15 @@ static void generateRegistrationComplete(nr_ue_nas_t *nas, } } -void decodeDownlinkNASTransport(as_nas_info_t *initialNasMsg, uint8_t *pdu_buffer) +/** + * @brief Handle DL NAS Transport and process piggybacked 5GSM messages + */ +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) { - uint8_t *ip_p = pdu_buffer + 39; - char ip[20]; - sprintf(ip, "%d.%d.%d.%d", *(ip_p), *(ip_p + 1), *(ip_p + 2), *(ip_p + 3)); - LOG_A(NAS, "Received PDU Session Establishment Accept\n"); - tun_config(1, ip, NULL, "oaitun_ue"); - setup_ue_ipv4_route(1, ip, "oaitun_ue"); + LOG_A(NAS, "Received PDU Session Establishment Accept in DL NAS Transport\n"); + capture_pdu_session_establishment_accept_msg(pdu_buffer, msg_length); } else { LOG_E(NAS, "Received unexpected message in DLinformationTransfer %d\n", msg_type); } @@ -1415,7 +1414,7 @@ void *nas_nrue(void *args_p) handle_security_mode_command(nas, &initialNasMsg, pdu_buffer, pdu_length); break; case FGS_DOWNLINK_NAS_TRANSPORT: - decodeDownlinkNASTransport(&initialNasMsg, pdu_buffer); + handleDownlinkNASTransport(pdu_buffer, pdu_length); break; case REGISTRATION_ACCEPT: handle_registration_accept(nas, pdu_buffer, pdu_length); @@ -1423,32 +1422,9 @@ void *nas_nrue(void *args_p) case FGS_DEREGISTRATION_ACCEPT_UE_ORIGINATING: LOG_I(NAS, "received deregistration accept\n"); break; - case FGS_PDU_SESSION_ESTABLISHMENT_ACC: { - uint8_t offset = 0; - uint8_t *payload_container = pdu_buffer; - offset += SECURITY_PROTECTED_5GS_NAS_MESSAGE_HEADER_LENGTH; - uint32_t payload_container_length = htons(((dl_nas_transport_t *)(pdu_buffer + offset))->payload_container_length); - if ((payload_container_length >= PAYLOAD_CONTAINER_LENGTH_MIN) - && (payload_container_length <= PAYLOAD_CONTAINER_LENGTH_MAX)) - offset += (PLAIN_5GS_NAS_MESSAGE_HEADER_LENGTH + 3); - if (offset < NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.length) - payload_container = pdu_buffer + offset; - - while (offset < payload_container_length) { - if (*(payload_container + offset) == 0x29) { // PDU address IEI - if ((*(payload_container + offset + 1) == 0x05) && (*(payload_container + offset + 2) == 0x01)) { // IPV4 - uint8_t *ip_p = payload_container + offset + 3; - char ip[20]; - snprintf(ip, sizeof(ip), "%d.%d.%d.%d", *(ip_p), *(ip_p + 1), *(ip_p + 2), *(ip_p + 3)); - LOG_I(NAS, "Received PDU Session Establishment Accept, UE IP: %s\n", ip); - tun_config(1, ip, NULL, "oaitun_ue"); - setup_ue_ipv4_route(1, ip, "oaitun_ue"); - break; - } - } - offset++; - } - } break; + case FGS_PDU_SESSION_ESTABLISHMENT_ACC: + capture_pdu_session_establishment_accept_msg(pdu_buffer, pdu_length); + break; case FGS_PDU_SESSION_ESTABLISHMENT_REJ: LOG_E(NAS, "Received PDU Session Establishment reject\n"); break;