From 53c2392ff9ed5f4288a34a6e49eaae90d2750f53 Mon Sep 17 00:00:00 2001
From: Tien-Thinh Nguyen <Tien-Thinh.nguyen@eurecom.fr>
Date: Wed, 15 Apr 2020 21:48:39 +0200
Subject: [PATCH] Fix issues when 0x00 included in the message (AMF client)

---
 src/test/amf_client/amf-client.cpp | 268 +++++------------------------
 1 file changed, 43 insertions(+), 225 deletions(-)

diff --git a/src/test/amf_client/amf-client.cpp b/src/test/amf_client/amf-client.cpp
index 6fbffe6d..6d4c4f5b 100644
--- a/src/test/amf_client/amf-client.cpp
+++ b/src/test/amf_client/amf-client.cpp
@@ -22,61 +22,33 @@ static std::size_t callback(
     *(uint8_t*)(buffer) = value;    \
     size += sizeof(uint8_t)
 
-//---------------------------------------------------------------------------------------------
-unsigned char * format_string_as_hex(std::string str){
-  unsigned int str_len = str.length();
-  unsigned char * datavalue  = (unsigned char *)malloc(str_len/2 + 1);
-
-  unsigned char *data = (unsigned char *)malloc(str_len + 1);
-  memset(data,0,str_len + 1);
-
-  memcpy ((void *)data, (void *)str.c_str(),str_len);
-
-  std::cout << "Data: " << data << " (" << str_len <<" bytes)" <<std::endl;
-
-  std::cout <<"Data (formatted): \n";
-  for(int i=0;i<str_len;i++)
-  {
-    char datatmp[3] = {0};
-    memcpy(datatmp,&data[i],2);
-    // Ensure both characters are hexadecimal
-    bool bBothDigits = true;
-
-    for(int j = 0; j < 2; ++j)
-    {
-      if(!isxdigit(datatmp[j]))
-        bBothDigits = false;
-    }
-    if(!bBothDigits)
-      break;
-    // Convert two hexadecimal characters into one character
-    unsigned int nAsciiCharacter;
-    sscanf(datatmp, "%x", &nAsciiCharacter);
-    printf("%x ",nAsciiCharacter);
-    // Concatenate this character onto the output
-    datavalue[i/2] = (unsigned char)nAsciiCharacter;
-
-    // Skip the next character
-    i++;
-  }
-  printf("\n");
-
-  free(data);
-  data = nullptr;
-
-  return datavalue;
-}
-
 void send_pdu_session_establishment_request(std::string smf_ip_address)
 {
   std::cout << "[AMF N11] PDU Session Establishment Request"<<std::endl;
 
   nlohmann::json pdu_session_establishment_request;
-  std::string n1_msg = "2e0101c1ffff91";
-  std::string n2_msg;
+  //encode
+  /*
+    0000   2e 01 01 c1 ff ff 91 00 00 00 00 00 00 00 00 00
+   */
+  size_t buffer_size = 128;
+  char *buffer = (char *)calloc(1,buffer_size);
+  int  size = 0;
+  ENCODE_U8 (buffer, 0x2e , size);
+  ENCODE_U8 (buffer+size, 0x01 , size);
+  ENCODE_U8 (buffer+size, 0x01 , size);
+  ENCODE_U8 (buffer+size, 0xc1 , size);
+  ENCODE_U8 (buffer+size, 0xff , size);
+  ENCODE_U8 (buffer+size, 0xff , size);
+  //    ENCODE_U8 (buffer+size, 0x00 , size);
+  ENCODE_U8 (buffer+size, 0x91 , size);
 
-  //format string as hex
-  unsigned char *n1_msg_hex  = format_string_as_hex(n1_msg);
+  std::cout << "Buffer: "<<std::endl;
+  for(int i=0;i<size;i++)
+  {
+    printf("%02x ", buffer[i]);
+  }
+  std::cout << "Buffer: "<<std::endl;
 
   //Fill Json part
   //get supi and put into URL
@@ -101,21 +73,15 @@ void send_pdu_session_establishment_request(std::string smf_ip_address)
   pdu_session_establishment_request["smContextStatusUri"] = "smContextStatusUri";
 
   pdu_session_establishment_request["n1MessageContainer"]["n1MessageClass"] = "SM";
-  pdu_session_establishment_request["n1MessageContainer"]["n1MessageContent"]["contentId"] = "n1SmMsg"; //part 2
+  pdu_session_establishment_request["n1MessageContainer"]["n1MessageContent"]["contentId"] = "n1SmMsg"; // NAS
 
-  //N1SM
-  //pdu_session_establishment_request["n1SmMsg"] = "SM";
-  //pdu_session_establishment_request["n1SmMsg"]["contentId"] = "n1SmMsg"; //part 2
 
   CURL *curl = curl_easy_init();
 
-  //N1N2MessageTransfer Notification URI??
   std::string json_part = pdu_session_establishment_request.dump();
 
-  std::cout<< " Sending message to SMF....\n";
+  std::cout<< "Sending message to SMF....\n";
   if(curl) {
-    std::cout << "send curl command"<<std::endl;
-
     CURLcode res;
     struct curl_slist *headers = nullptr;
     struct curl_slist *slist = nullptr;
@@ -129,6 +95,7 @@ void send_pdu_session_establishment_request(std::string smf_ip_address)
     curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
     curl_easy_setopt(curl, CURLOPT_HTTPGET,1);
     curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 100L);
+    curl_easy_setopt(curl, CURLOPT_INTERFACE, "eno1:amf"); //hardcoded
 
     mime = curl_mime_init(curl);
     alt = curl_mime_init(curl);
@@ -139,13 +106,12 @@ void send_pdu_session_establishment_request(std::string smf_ip_address)
     curl_mime_type(part, "application/json");
 
     part = curl_mime_addpart(mime);
-    std::string n1_msg = "2e0101c1ffff95";
-    curl_mime_data(part, reinterpret_cast<const char*>(n1_msg_hex), CURL_ZERO_TERMINATED);
+    //curl_mime_data(part, reinterpret_cast<const char*>(n1_msg_hex), CURL_ZERO_TERMINATED);
+    curl_mime_data(part, reinterpret_cast<const char*>(buffer), size);
     curl_mime_type(part, "application/vnd.3gpp.5gnas");
     //curl_mime_name (part, "n1SmMsg");
 
     curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
-    //res = curl_easy_perform(curl);
 
     // Response information.
     long httpCode(0);
@@ -164,16 +130,15 @@ void send_pdu_session_establishment_request(std::string smf_ip_address)
       response_data = nlohmann::json::parse(*httpData.get());
     } catch (nlohmann::json::exception& e){
       std::cout << "Could not get the cause from the response" <<std::endl;
-      //Set the default Cause
-      response_data["cause"] = "504 Gateway Timeout";
+
     }
-    std::cout << "[AMF N11] PDU session establishment request, response from SMF, Http Code " << httpCode << " cause  "<<  response_data["cause"].dump().c_str()<<std::endl;
+    std::cout << "[AMF N11] PDU session establishment request, response from SMF, Http Code " << httpCode <<std::endl;
 
     curl_slist_free_all(headers);
     curl_easy_cleanup(curl);
     curl_mime_free(mime);
   }
-
+  free(buffer);
 }
 
 
@@ -181,20 +146,17 @@ void send_pdu_session_update_sm_context_establishment(std::string smf_ip_address
 {
   std::cout << "[AMF N11] send_pdu_session_update_sm_context_establishment"<<std::endl;
 
-  nlohmann::json pdu_session_modification_request;
-  std::string n2_msg = "0003e0ac0a0501000000010000";
-
-  //format string as hex
-  unsigned char *n2_msg_hex  = format_string_as_hex(n2_msg);
+  nlohmann::json pdu_session_update_request;
 
   //encode
+  /*
+  00 03 e0 ac 0a 05 01 00 00 00 01 00 3c
+   */
   size_t buffer_size = 128;
   char *buffer = (char *)calloc(1,buffer_size);
-
   int  size = 0;
-
-  ENCODE_U8 (buffer, 0 , size);
-  ENCODE_U8 (buffer+size, 3 , size);
+  ENCODE_U8 (buffer, 0x00 , size);
+  ENCODE_U8 (buffer+size, 0x03 , size);
   ENCODE_U8 (buffer+size, 0xe0 , size);
   ENCODE_U8 (buffer+size, 0xac , size);
   ENCODE_U8 (buffer+size, 0x0a , size);
@@ -205,17 +167,7 @@ void send_pdu_session_update_sm_context_establishment(std::string smf_ip_address
   ENCODE_U8 (buffer+size, 0x00 , size);
   ENCODE_U8 (buffer+size, 0x01 , size);
   ENCODE_U8 (buffer+size, 0x00 , size);
-  ENCODE_U8 (buffer+size, 0x3c , size);
-
-
-/*
-  0000   00 00 04 00 82 00 04 00 01 00 02 00 8b 00 0a 01
-  0010   f0 04 03 02 01 7f 00 00 01 00 86 00 01 10 00 88
-  0020   00 07 00 3c 00 00 3c 00 00 00 00 00 00 00 00 00
-  0030   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-  0040   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-*/
-
+  ENCODE_U8 (buffer+size, 0x3c , size);  //QFI: 60
 
   std::cout << "Buffer: "<<std::endl;
   for(int i=0;i<2;i++)
@@ -225,30 +177,21 @@ void send_pdu_session_update_sm_context_establishment(std::string smf_ip_address
   std::cout << "Buffer: "<<std::endl;
 
   //Fill Json part
-  //get supi and put into URL
-  std::string supi_str;
-  //std::string url = std::string("http://172.16.1.101/nsmf-pdusession/v2/sm-contexts");
   //std::string url = std::string("http://172.16.1.101/nsmf-pdusession/v2/sm-contexts/imsi-200000000000001/modify");
   std::string url = std::string("http://");
   url.append(smf_ip_address);
   url.append(std::string("/nsmf-pdusession/v2/sm-contexts/1/modify"));
 
   //Fill the json part
-  pdu_session_modification_request["n2SmInfoType"] = "PDU_RES_SETUP_RSP";
-  pdu_session_modification_request["n2SmInfo"]["contentId"] = "n2SmMsg"; //part 2
-
-  //N1SM
-  //pdu_session_establishment_request["n1SmMsg"] = "SM";
-  //pdu_session_establishment_request["n1SmMsg"]["contentId"] = "n1SmMsg"; //part 2
+  pdu_session_update_request["n2SmInfoType"] = "PDU_RES_SETUP_RSP";
+  pdu_session_update_request["n2SmInfo"]["contentId"] = "n2SmMsg"; //NGAP
 
   CURL *curl = curl_easy_init();
 
-  //N1N2MessageTransfer Notification URI??
-  std::string json_part = pdu_session_modification_request.dump();
+  std::string json_part = pdu_session_update_request.dump();
 
-  std::cout<< " Sending message to SMF....\n";
+  std::cout<< "Sending message to SMF....\n";
   if(curl) {
-    std::cout << "send curl command"<<std::endl;
 
     CURLcode res;
     struct curl_slist *headers = nullptr;
@@ -263,6 +206,8 @@ void send_pdu_session_update_sm_context_establishment(std::string smf_ip_address
     curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
     curl_easy_setopt(curl, CURLOPT_HTTPGET,1);
     curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 100L);
+    curl_easy_setopt(curl, CURLOPT_INTERFACE, "eno1:amf"); //hardcoded
+
 
     mime = curl_mime_init(curl);
     alt = curl_mime_init(curl);
@@ -274,137 +219,11 @@ void send_pdu_session_update_sm_context_establishment(std::string smf_ip_address
 
     part = curl_mime_addpart(mime);
     curl_mime_data(part, reinterpret_cast<const char*>(buffer), size);
-    //curl_mime_data(part, "\x00\x03\xe0\xac\x0a\x05\x01\x01\x01\x01\x01\x00\x00", CURL_ZERO_TERMINATED);
-    //curl_mime_data(part, "\x2e\x01\x01\xc1\xff\xff\x95", CURL_ZERO_TERMINATED);
-
 
     curl_mime_type(part, "application/vnd.3gpp.ngap");
     curl_mime_name (part, "n2SmMsg");
 
     curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
-    //res = curl_easy_perform(curl);
-
-    // Response information.
-    long httpCode(0);
-    std::unique_ptr<std::string> httpData(new std::string());
-
-    // Hook up data handling function.
-    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &callback);
-    curl_easy_setopt(curl, CURLOPT_WRITEDATA, httpData.get());
-
-    res = curl_easy_perform(curl);
-    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
-
-    //get cause from the response
-    nlohmann::json response_data;
-    try{
-      response_data = nlohmann::json::parse(*httpData.get());
-    } catch (nlohmann::json::exception& e){
-      std::cout << "Could not get the cause from the response" <<std::endl;
-      //Set the default Cause
-      response_data["cause"] = "504 Gateway Timeout";
-    }
-    std::cout << "[AMF N11] PDU session modification request, response from SMF, Http Code " << httpCode << " cause  "<<  response_data["cause"].dump().c_str()<<std::endl;
-
-    curl_slist_free_all(headers);
-    curl_easy_cleanup(curl);
-    curl_mime_free(mime);
-  }
-
-}
-
-void send_pdu_session_update_sm_context_modification(std::string smf_ip_address)
-{
-  std::cout << "[AMF N11] send_pdu_session_update_sm_context_modification"<<std::endl;
-
-  nlohmann::json pdu_session_modification_request;
-  std::string n2_msg = "0003e0ac0a0501000000010000";
-
-  //format string as hex
-  unsigned char *n2_msg_hex  = format_string_as_hex(n2_msg);
-
-  //encode
-  size_t buffer_size = 128;
-  char *buffer = (char *)calloc(1,buffer_size);
-
-  int  size = 0;
-
-  ENCODE_U8 (buffer, 0x2e , size);
-  ENCODE_U8 (buffer+size, 0x01 , size);
-  ENCODE_U8 (buffer+size, 0x01 , size);
-  ENCODE_U8 (buffer+size, 0xc1 , size);
-  ENCODE_U8 (buffer+size, 0xff , size);
-  ENCODE_U8 (buffer+size, 0xff , size);
-  ENCODE_U8 (buffer+size, 0x95 , size);
-
-  ////step 1.a,UE-initiated: SM Context ID + N1 (PDU Session Modification Request)
-
-
-  std::cout << "Buffer: "<<std::endl;
-  for(int i=0;i<2;i++)
-  {
-    printf("%02x ", buffer[i]);
-  }
-  std::cout << "Buffer: "<<std::endl;
-
-  //Fill Json part
-  //get supi and put into URL
-  std::string supi_str;
-  //std::string url = std::string("http://172.16.1.101/nsmf-pdusession/v2/sm-contexts");
-  //std::string url = std::string("http://172.16.1.101/nsmf-pdusession/v2/sm-contexts/imsi-200000000000001/modify");
-  std::string url = std::string("http://");
-  url.append(smf_ip_address);
-  url.append(std::string("/nsmf-pdusession/v2/sm-contexts/1/modify"));
-
-  //Fill the json part
-  pdu_session_modification_request["n1SmMsg"]["contentId"] = "n1SmMsg"; //part 2
-
-  //N1SM
-  //pdu_session_establishment_request["n1SmMsg"] = "SM";
-  //pdu_session_establishment_request["n1SmMsg"]["contentId"] = "n1SmMsg"; //part 2
-
-  CURL *curl = curl_easy_init();
-
-  //N1N2MessageTransfer Notification URI??
-  std::string json_part = pdu_session_modification_request.dump();
-
-  std::cout<< " Sending message to SMF....\n";
-  if(curl) {
-    std::cout << "send curl command"<<std::endl;
-
-    CURLcode res;
-    struct curl_slist *headers = nullptr;
-    struct curl_slist *slist = nullptr;
-    curl_mime *mime;
-    curl_mime *alt;
-    curl_mimepart *part;
-
-    headers = curl_slist_append(headers, "charsets: utf-8");
-    headers = curl_slist_append(headers, "content-type: multipart/related");
-    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
-    curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
-    curl_easy_setopt(curl, CURLOPT_HTTPGET,1);
-    curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 100L);
-
-    mime = curl_mime_init(curl);
-    alt = curl_mime_init(curl);
-
-    //part with N1N2MessageTransferReqData (JsonData)
-    part = curl_mime_addpart(mime);
-    curl_mime_data(part, json_part.c_str(), CURL_ZERO_TERMINATED);
-    curl_mime_type(part, "application/json");
-
-    part = curl_mime_addpart(mime);
-    curl_mime_data(part, reinterpret_cast<const char*>(buffer), size);
-    //curl_mime_data(part, "\x00\x03\xe0\xac\x0a\x05\x01\x01\x01\x01\x01\x00\x00", CURL_ZERO_TERMINATED);
-    //curl_mime_data(part, "\x2e\x01\x01\xc1\xff\xff\x95", CURL_ZERO_TERMINATED);
-
-
-    curl_mime_type(part, "application/vnd.3gpp.5gnas");
-    curl_mime_name (part, "n1SmMsg");
-
-    curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
-    //res = curl_easy_perform(curl);
 
     // Response information.
     long httpCode(0);
@@ -432,7 +251,7 @@ void send_pdu_session_update_sm_context_modification(std::string smf_ip_address)
     curl_easy_cleanup(curl);
     curl_mime_free(mime);
   }
-
+  free(buffer);
 }
 
 int main(int argc, char* argv[])
@@ -466,7 +285,6 @@ int main(int argc, char* argv[])
   send_pdu_session_establishment_request(smf_ip_address);
   usleep(100000);
   send_pdu_session_update_sm_context_establishment(smf_ip_address);
-  //send_pdu_session_update_sm_context_modification(smf_ip_address);
   return 0;
 }
 
-- 
GitLab