From 305a268173c0c57991e22d54d33eb72c04b892c6 Mon Sep 17 00:00:00 2001
From: Laurent Thomas <lts@open-cells.com>
Date: Wed, 30 Jun 2021 16:49:33 +0200
Subject: [PATCH] bug fix in F1

---
 openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c |  4 +-
 openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c   |  4 +-
 openair2/RRC/NR/rrc_gNB.c                 |  4 +
 openair3/NAS/NR_UE/nr_nas_msg_sim.c       | 97 ++++++++++++++---------
 openair3/NAS/NR_UE/nr_nas_msg_sim.h       | 31 ++++++++
 5 files changed, 100 insertions(+), 40 deletions(-)

diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c
index c9d7cf7696..e5ecf3b65c 100644
--- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c
+++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c
@@ -627,7 +627,9 @@ srb_found:
   }
   else {
     MessageDef  *message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, F1AP_DL_RRC_MESSAGE);
-    F1AP_DL_RRC_MESSAGE (message_p).rrc_container        = (uint8_t*)buf;
+    uint8_t *message_buffer = itti_malloc (TASK_RRC_GNB, TASK_CU_F1, size);
+    memcpy (message_buffer, buf, size);
+    F1AP_DL_RRC_MESSAGE (message_p).rrc_container        = message_buffer;
     F1AP_DL_RRC_MESSAGE (message_p).rrc_container_length = size;
     F1AP_DL_RRC_MESSAGE (message_p).gNB_CU_ue_id         = 0;
     F1AP_DL_RRC_MESSAGE (message_p).gNB_DU_ue_id         = 0;
diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c
index b2d29a88c6..acbb6b4f45 100644
--- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c
+++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c
@@ -491,9 +491,11 @@ rb_found:
     if (NODE_IS_DU(type) && is_srb == 1) {
       MessageDef *msg;
       msg = itti_alloc_new_message(TASK_RLC_ENB, 0, F1AP_UL_RRC_MESSAGE);
+      uint8_t *message_buffer = itti_malloc (TASK_RLC_ENB, TASK_DU_F1, size);
+      memcpy (message_buffer, buf, size);
       F1AP_UL_RRC_MESSAGE(msg).rnti = ue->rnti;
       F1AP_UL_RRC_MESSAGE(msg).srb_id = rb_id;
-      F1AP_UL_RRC_MESSAGE(msg).rrc_container = (unsigned char *)buf;
+      F1AP_UL_RRC_MESSAGE(msg).rrc_container = message_buffer;
       F1AP_UL_RRC_MESSAGE(msg).rrc_container_length = size;
       itti_send_msg_to_task(TASK_DU_F1, ENB_MODULE_ID_TO_INSTANCE(0 /*ctxt_pP->module_id*/), msg);
       return;
diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c
index bcdf0967ae..1bef151704 100755
--- a/openair2/RRC/NR/rrc_gNB.c
+++ b/openair2/RRC/NR/rrc_gNB.c
@@ -1361,6 +1361,10 @@ rrc_gNB_process_RRCReconfigurationComplete(
       F1AP_UE_CONTEXT_SETUP_REQ (message_p).gNB_CU_ue_id     = 0;
       F1AP_UE_CONTEXT_SETUP_REQ (message_p).gNB_DU_ue_id = 0;
       F1AP_UE_CONTEXT_SETUP_REQ (message_p).rnti = ue_context_pP->ue_context.rnti;
+      F1AP_UE_CONTEXT_SETUP_REQ (message_p).mcc              = RC.nrrrc[0]->configuration.mcc[0];
+      F1AP_UE_CONTEXT_SETUP_REQ (message_p).mnc              = RC.nrrrc[0]->configuration.mnc[0];
+      F1AP_UE_CONTEXT_SETUP_REQ (message_p).mnc_digit_length = RC.nrrrc[0]->configuration.mnc_digit_length[0];
+      F1AP_UE_CONTEXT_SETUP_REQ (message_p).nr_cellid        = RC.nrrrc[0]->nr_cellid;
       itti_send_msg_to_task (TASK_CU_F1, ctxt_pP->module_id, message_p);
       LOG_I(RRC, "Send F1AP_UE_CONTEXT_SETUP_REQ with ITTI\n");
     }
diff --git a/openair3/NAS/NR_UE/nr_nas_msg_sim.c b/openair3/NAS/NR_UE/nr_nas_msg_sim.c
index f69231cc18..ca7df4cac7 100644
--- a/openair3/NAS/NR_UE/nr_nas_msg_sim.c
+++ b/openair3/NAS/NR_UE/nr_nas_msg_sim.c
@@ -713,6 +713,31 @@ void generatePduSessionEstablishRequest(as_nas_info_t *initialNasMsg){
 }
 
 
+uint8_t get_msg_type(uint8_t *pdu_buffer, uint32_t length) {
+  uint8_t          msg_type = 0;
+  uint8_t          offset   = 0;
+  nas_msg_header_t nas_msg_header;
+
+  if ((pdu_buffer != NULL) && (length > 0)) {
+    if (((nas_msg_header_t *)(pdu_buffer))->choice.security_protected_nas_msg_header_t.security_header_type > 0) {
+      offset += SECURITY_PROTECTED_5GS_NAS_MESSAGE_HEADER_LENGTH;
+      if (offset < length) {
+        msg_type = ((mm_msg_header_t *)(pdu_buffer + offset))->message_type;
+
+        if (msg_type == FGS_DOWNLINK_NAS_TRANSPORT) {
+          msg_type = ((dl_nas_transport_t *)(pdu_buffer+ offset))->sm_nas_msg_header.message_type;
+        }
+      }
+    } else { // plain 5GS NAS message
+      msg_type = ((nas_msg_header_t *)(pdu_buffer))->choice.plain_nas_msg_header.message_type;
+    }
+  } else {
+    LOG_I(NAS, "[UE] Received invalid downlink message\n");
+  }
+
+  return msg_type;
+}
+
 void *nas_nrue_task(void *args_p)
 {
   MessageDef           *msg_p;
@@ -784,23 +809,8 @@ void *nas_nrue_task(void *args_p)
               NAS_CONN_ESTABLI_CNF (msg_p).errCode, NAS_CONN_ESTABLI_CNF (msg_p).nasMsg.length);
 
         pdu_buffer = NAS_CONN_ESTABLI_CNF (msg_p).nasMsg.data;
-        if((pdu_buffer + 1) != NULL){
-          if (*(pdu_buffer + 1) > 0 ) {
-            if((pdu_buffer + 9) != NULL){
-                msg_type = *(pdu_buffer + 9);
-            } else {
-              LOG_W(NAS, "[UE] Received invalid downlink message\n");
-              break;
-            }
-          } else {
-            if((pdu_buffer + 2) != NULL){
-              msg_type = *(pdu_buffer + 2);
-            } else {
-                LOG_W(NAS, "[UE] Received invalid downlink message\n");
-                break;
-            }
-          }
-        }
+        msg_type = get_msg_type(pdu_buffer, NAS_CONN_ESTABLI_CNF (msg_p).nasMsg.length);
+
         if(msg_type == REGISTRATION_ACCEPT){
           LOG_I(NAS, "[UE] Received REGISTRATION ACCEPT message\n");
 
@@ -829,17 +839,38 @@ void *nas_nrue_task(void *args_p)
             itti_send_msg_to_task(TASK_RRC_NRUE, instance, message_p);
             LOG_I(NAS, "Send NAS_UPLINK_DATA_REQ message(PduSessionEstablishRequest)\n");
           }
-        }
-        else if((pdu_buffer + 16) != NULL){
-          msg_type = *(pdu_buffer + 16);
-          if(msg_type == FGS_PDU_SESSION_ESTABLISHMENT_ACC){
-            sprintf(baseNetAddress, "%d.%d", *(pdu_buffer + 39),*(pdu_buffer + 40));
-            int third_octet = *(pdu_buffer + 41);
-            int fourth_octet = *(pdu_buffer + 42);
-            LOG_I(NAS, "Received PDU Session Establishment Accept\n");
-            nas_config(1,third_octet,fourth_octet,"ue");
+        } else if(msg_type == FGS_PDU_SESSION_ESTABLISHMENT_ACC){
+            uint8_t offset = 0;
+            uint8_t *payload_container = NULL;
+            offset += SECURITY_PROTECTED_5GS_NAS_MESSAGE_HEADER_LENGTH;
+            uint16_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;
+            }
+            offset = 0;
+
+            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
+                  nas_getparams();
+                  netlink_init_tun("ue", 1);
+                  sprintf(baseNetAddress, "%d.%d", *(payload_container+offset+3), *(payload_container+offset+4));
+                  int third_octet = *(payload_container+offset+5);
+                  int fourth_octet = *(payload_container+offset+6);
+                  LOG_I(NAS, "Received PDU Session Establishment Accept, UE IP: %d.%d.%d.%d\n",
+                    *(payload_container+offset+3), *(payload_container+offset+4),
+                    *(payload_container+offset+5), *(payload_container+offset+6));
+                  nas_config(1,third_octet,fourth_octet,"oaitun_ue");
+                  break;
+                }
+              }
+              offset++;
+            }
           }
-        }
 
         break;
       }
@@ -866,17 +897,7 @@ void *nas_nrue_task(void *args_p)
         as_nas_info_t initialNasMsg={0};
 
         pdu_buffer = NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.data;
-        if((pdu_buffer + 1) != NULL){
-          if (*(pdu_buffer + 1) > 0 ) {
-            msg_type = *(pdu_buffer + 9);
-          } else {
-            msg_type = *(pdu_buffer + 2);
-          }
-        }
-        if((pdu_buffer + 2) == NULL){
-          LOG_W(NAS, "[UE] Received invalid downlink message\n");
-          return 0;
-        }
+        msg_type = get_msg_type(pdu_buffer, NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.length);
 
         switch(msg_type){
           case FGS_IDENTITY_REQUEST:
diff --git a/openair3/NAS/NR_UE/nr_nas_msg_sim.h b/openair3/NAS/NR_UE/nr_nas_msg_sim.h
index 348c27ecc8..3ec827117a 100644
--- a/openair3/NAS/NR_UE/nr_nas_msg_sim.h
+++ b/openair3/NAS/NR_UE/nr_nas_msg_sim.h
@@ -64,6 +64,10 @@
 
 #define INITIAL_REGISTRATION                               0b001
 
+#define PLAIN_5GS_NAS_MESSAGE_HEADER_LENGTH                3
+#define SECURITY_PROTECTED_5GS_NAS_MESSAGE_HEADER_LENGTH   7
+#define PAYLOAD_CONTAINER_LENGTH_MIN                       3
+#define PAYLOAD_CONTAINER_LENGTH_MAX                       65537
 
 typedef enum fgs_protocol_discriminator_e {
   /* Protocol discriminator identifier for 5GS Mobility Management */
@@ -116,6 +120,33 @@ typedef union {
   fgs_nas_message_plain_t plain;
 } fgs_nas_message_t;
 
+typedef struct {
+  union {
+    mm_msg_header_t plain_nas_msg_header;
+    struct security_protected_nas_msg_header_s {
+      uint8_t  ex_protocol_discriminator;
+      uint8_t  security_header_type;
+      uint16_t message_authentication_code1;
+      uint16_t message_authentication_code2;
+      uint8_t  sequence_number;
+    } security_protected_nas_msg_header_t;
+  } choice;
+} nas_msg_header_t;
+
+typedef struct {
+  uint8_t ex_protocol_discriminator;
+  uint8_t pdu_session_id;
+  uint8_t PTI;
+  uint8_t message_type;
+} fgs_sm_nas_msg_header_t;
+
+typedef struct {
+    mm_msg_header_t         plain_nas_msg_header;
+    uint8_t                 payload_container_type;
+    uint16_t                payload_container_length;
+    fgs_sm_nas_msg_header_t sm_nas_msg_header;
+} dl_nas_transport_t;
+
 void generateRegistrationRequest(as_nas_info_t *initialNasMsg, int Mod_id);
 void generateSecurityModeComplete(as_nas_info_t *initialNasMsg);
 void generateRegistrationComplete(as_nas_info_t *initialNasMsg, SORTransparentContainer *sortransparentcontainer);
-- 
2.26.2