MME2 changes - Propped commits from openmme/paging branch. Added scripts
for code gen
Change-Id: Ie55032217232214ac8544ca76ea34335205329e4
diff --git a/src/s1ap/handlers/s1ap_tau_response_handler.c b/src/s1ap/handlers/s1ap_tau_response_handler.c
new file mode 100644
index 0000000..8838da3
--- /dev/null
+++ b/src/s1ap/handlers/s1ap_tau_response_handler.c
@@ -0,0 +1,345 @@
+/*
+ * Copyright 2019-present Open Networking Foundation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdint.h>
+
+
+
+#include "log.h"
+#include "err_codes.h"
+#include "options.h"
+#include "ipc_api.h"
+#include "main.h"
+#include "s1ap.h"
+#include "s1ap_config.h"
+#include "sctp_conn.h"
+#include "s1ap_structs.h"
+#include "s1ap_msg_codes.h"
+#include "msgType.h"
+extern s1ap_config g_s1ap_cfg;
+extern ipc_handle ipc_S1ap_Hndl;
+static Buffer g_buffer;
+static int
+get_tau_rsp_protoie_value(struct proto_IE *value, struct tauResp_Q_msg *g_tauRespInfo)
+{
+
+ value->no_of_IEs = TAU_RSP_NO_OF_IES;
+
+ value->data = (proto_IEs *) malloc(TAU_RSP_NO_OF_IES*
+ sizeof(proto_IEs));
+
+ value->data[0].val.mme_ue_s1ap_id = g_tauRespInfo->ue_idx;
+ value->data[1].val.enb_ue_s1ap_id = g_tauRespInfo->s1ap_enb_ue_id;
+
+ log_msg(LOG_INFO, "mme_ue_s1ap_id %d and enb_ue_s1ap_id %d\n",
+ g_tauRespInfo->ue_idx, g_tauRespInfo->s1ap_enb_ue_id);
+
+ /* TODO: Add enum for security header type */
+ value->data[2].val.nas.header.security_header_type = IntegrityProtectedCiphered;
+ value->data[2].val.nas.header.proto_discriminator = EPSMobilityManagementMessages;
+ if(g_tauRespInfo->status == 0)
+ value->data[2].val.nas.header.message_type = TauAccept;
+ else
+ value->data[2].val.nas.header.message_type = TauReject;
+ value->data[2].val.nas.header.nas_security_param = 0;
+ /* placeholder for mac. mac value will be calculated later */
+ uint8_t mac[MAC_SIZE] = {0};
+ memcpy(value->data[2].val.nas.header.mac, mac, MAC_SIZE);
+ value->data[2].val.nas.header.seq_no = g_tauRespInfo->dl_seq_no;
+ value->data[2].val.nas.header.eps_bearer_identity = 0;
+ value->data[2].val.nas.header.procedure_trans_identity = 1;
+ value->data[2].val.nas.elements_len = TAU_RSP_NO_OF_NAS_IES;
+ value->data[2].val.nas.elements = (nas_pdu_elements *) malloc(TAU_RSP_NO_OF_NAS_IES * sizeof(nas_pdu_elements));
+ nas_pdu_elements *nasIEs = value->data[2].val.nas.elements;
+ uint8_t nasIeCnt = 0;
+ nasIEs[nasIeCnt].pduElement.eps_res = 0; /* TA updated */
+ nasIeCnt++;
+ nasIEs[nasIeCnt].pduElement.spare = 0; /* TA updated */
+ nasIeCnt++;
+
+ return SUCCESS;
+}
+
+static int
+tau_rsp_processing(struct tauResp_Q_msg *g_tauRespInfo)
+{
+
+ struct s1ap_PDU s1apPDU= {0};
+
+ uint8_t nas_len_pos;
+ uint8_t s1ap_len_pos;
+ uint8_t mac_data_pos;
+ uint8_t datalen;
+ uint8_t u8value;
+
+ if(g_tauRespInfo->status != 0)
+ {
+ /* Assigning values to s1apPDU */
+ s1apPDU.procedurecode = id_errorIndication;
+ s1apPDU.criticality = CRITICALITY_IGNORE;
+ get_tau_rsp_protoie_value(&s1apPDU.value,g_tauRespInfo);
+ g_buffer.pos = 0;
+
+ uint8_t initiating_message = 0; /* TODO: Add enum */
+ buffer_copy(&g_buffer, &initiating_message,
+ sizeof(initiating_message));
+
+ buffer_copy(&g_buffer, &s1apPDU.procedurecode,
+ sizeof(s1apPDU.procedurecode));
+
+ buffer_copy(&g_buffer, &s1apPDU.criticality,
+ sizeof(s1apPDU.criticality));
+
+ s1ap_len_pos = g_buffer.pos;
+
+ /* length of S1ap message */
+ u8value = 0;
+ buffer_copy(&g_buffer, &u8value, sizeof(u8value));
+
+ /* TODO remove hardcoded values */
+ unsigned char chProtoIENo[3] = {0,0,2};
+
+ buffer_copy(&g_buffer, chProtoIENo, 3);
+
+ unsigned char tmpStr[4];
+
+ /* id-eNB-UE-S1AP-ID */
+
+ uint16_t protocolIe_Id = id_eNB_UE_S1AP_ID;
+ uint8_t protocolIe_criticality = CRITICALITY_REJECT;
+ copyU16(tmpStr, protocolIe_Id);
+ buffer_copy(&g_buffer, tmpStr,
+ sizeof(protocolIe_Id));
+
+ buffer_copy(&g_buffer, &protocolIe_criticality,
+ sizeof(protocolIe_criticality));
+
+
+ /* TODO needs proper handling*/
+ unsigned char enb_ue_id[3];
+ datalen = copyU16(enb_ue_id,
+ s1apPDU.value.data[1].val.enb_ue_s1ap_id);
+ buffer_copy(&g_buffer, &datalen, sizeof(datalen));
+ buffer_copy(&g_buffer, enb_ue_id, datalen);
+
+ unsigned char cause[6] = {0,2,40,2,4, 0};
+ buffer_copy(&g_buffer, cause, sizeof(cause));
+
+ /* Copy length to s1ap length field */
+ datalen = g_buffer.pos - s1ap_len_pos - 1;
+ memcpy(g_buffer.buf + s1ap_len_pos, &datalen, sizeof(datalen));
+ return E_FAIL;
+ }
+ /* Assigning values to s1apPDU */
+ s1apPDU.procedurecode = id_downlinkNASTransport;
+ s1apPDU.criticality = CRITICALITY_IGNORE;
+
+ get_tau_rsp_protoie_value(&s1apPDU.value,g_tauRespInfo);
+
+ /* Copy values to buffer from s1apPDU */
+
+ g_buffer.pos = 0;
+
+ uint8_t initiating_message = 0; /* TODO: Add enum */
+ buffer_copy(&g_buffer, &initiating_message,
+ sizeof(initiating_message));
+
+ buffer_copy(&g_buffer, &s1apPDU.procedurecode,
+ sizeof(s1apPDU.procedurecode));
+
+ buffer_copy(&g_buffer, &s1apPDU.criticality,
+ sizeof(s1apPDU.criticality));
+
+ s1ap_len_pos = g_buffer.pos;
+
+ /* length of S1ap message */
+ u8value = 0;
+ buffer_copy(&g_buffer, &u8value, sizeof(u8value));
+
+ /* TODO remove hardcoded values */
+ unsigned char chProtoIENo[3] = {0,0,3};
+
+ buffer_copy(&g_buffer, chProtoIENo, 3);
+
+ unsigned char tmpStr[4];
+
+ /* id-MME-UE-S1AP-ID */
+ uint16_t protocolIe_Id = id_MME_UE_S1AP_ID;
+ copyU16(tmpStr, protocolIe_Id);
+ buffer_copy(&g_buffer, tmpStr,
+ sizeof(protocolIe_Id));
+
+ uint8_t protocolIe_criticality = CRITICALITY_REJECT;
+ buffer_copy(&g_buffer, &protocolIe_criticality,
+ sizeof(protocolIe_criticality));
+
+ /* TODO needs proper handling*/
+ unsigned char mme_ue_id[3];
+ datalen = copyU16(mme_ue_id,
+ s1apPDU.value.data[0].val.mme_ue_s1ap_id);
+ buffer_copy(&g_buffer, &datalen, sizeof(datalen));
+ buffer_copy(&g_buffer, mme_ue_id, datalen);
+
+ /* id-eNB-UE-S1AP-ID */
+
+ protocolIe_Id = id_eNB_UE_S1AP_ID;
+ copyU16(tmpStr, protocolIe_Id);
+ buffer_copy(&g_buffer, tmpStr,
+ sizeof(protocolIe_Id));
+
+ buffer_copy(&g_buffer, &protocolIe_criticality,
+ sizeof(protocolIe_criticality));
+
+ /* TODO needs proper handling*/
+ unsigned char enb_ue_id[3];
+ datalen = copyU16(enb_ue_id,
+ s1apPDU.value.data[1].val.enb_ue_s1ap_id);
+ buffer_copy(&g_buffer, &datalen, sizeof(datalen));
+ buffer_copy(&g_buffer, enb_ue_id, datalen);
+
+ /* id-NAS-PDU */
+ protocolIe_Id = id_NAS_PDU;
+ copyU16(tmpStr, protocolIe_Id);
+ buffer_copy(&g_buffer, tmpStr,
+ sizeof(protocolIe_Id));
+ buffer_copy(&g_buffer, &protocolIe_criticality,
+ sizeof(protocolIe_criticality));
+
+ nas_len_pos = g_buffer.pos;
+ datalen = 0;
+ buffer_copy(&g_buffer, &datalen, sizeof(datalen));
+ buffer_copy(&g_buffer, &datalen, sizeof(datalen));
+
+ struct nasPDU *nas = &(s1apPDU.value.data[2].val.nas);
+ struct nas_pdu_header *nas_hdr = &(s1apPDU.value.data[2].val.nas.header);
+
+ u8value = (nas->header.security_header_type << 4) |
+ nas->header.proto_discriminator;
+ buffer_copy(&g_buffer, &u8value, sizeof(u8value));
+
+ /* mac */
+ /* placeholder for mac. mac value will be calculated later */
+ buffer_copy(&g_buffer, nas_hdr->mac, MAC_SIZE);
+ mac_data_pos = g_buffer.pos;
+
+ /* sequence number */
+ buffer_copy(&g_buffer, &(nas_hdr->seq_no),
+ sizeof(nas_hdr->seq_no));
+
+ /* security header and protocol discriminator */
+ nas_hdr->security_header_type = Plain;
+ u8value = (0 << 4 | nas_hdr->proto_discriminator);
+ buffer_copy(&g_buffer, &u8value, sizeof(u8value));
+
+ /* message type */
+ buffer_copy(&g_buffer, &nas->header.message_type,
+ sizeof(nas->header.message_type));
+
+
+ u8value = 0;
+ buffer_copy(&g_buffer, &u8value, sizeof(u8value));
+ u8value = 0x5a;
+ buffer_copy(&g_buffer, &u8value, sizeof(u8value));
+#define DISABLE_TAU 0
+#if DISABLE_TAU
+ u8value = 0xe0;
+#else
+ u8value = 0x21;
+#endif
+ buffer_copy(&g_buffer, &u8value, sizeof(u8value));
+
+#if 1
+ /* adding GUTI */
+ u8value = 0x50; /* element id TODO: define macro or enum */
+ buffer_copy(&g_buffer, &u8value, sizeof(u8value));
+ datalen = 11;
+ buffer_copy(&g_buffer, &datalen, sizeof(datalen));
+ u8value = 246; /* TODO: remove hard coding */
+ buffer_copy(&g_buffer, &u8value, sizeof(u8value));
+
+ unsigned char x3 = g_tauRespInfo->tai.plmn_id.idx[2];
+ unsigned char x2 = g_tauRespInfo->tai.plmn_id.idx[1];
+ unsigned char x31 = x3 >> 4;
+ unsigned char x32 = x3 & 0xf;
+ unsigned char x21 = x2 >> 4;
+ unsigned char x22 = x2 & 0xf;
+ x3 = x21 | (x32 <<4);
+ x2 = (x31 << 4) | x22;
+ g_tauRespInfo->tai.plmn_id.idx[1] = x2;
+ g_tauRespInfo->tai.plmn_id.idx[2] = x3;
+
+ buffer_copy(&g_buffer, &g_tauRespInfo->tai.plmn_id, 3);
+
+ uint16_t grpid = htons(g_s1ap_cfg.mme_group_id);
+ buffer_copy(&g_buffer, &grpid, sizeof(grpid));
+
+ u8value = g_s1ap_cfg.mme_code;
+ buffer_copy(&g_buffer, &u8value, sizeof(u8value));
+
+ uint32_t mtmsi = htonl(g_tauRespInfo->m_tmsi);
+ buffer_copy(&g_buffer, &(mtmsi), sizeof(mtmsi));
+#endif
+
+
+
+#if 1
+ /*TODO : Experiment */
+ u8value = 0x23; /* element id TODO: define macro or enum */
+ buffer_copy(&g_buffer, &u8value, sizeof(u8value));
+ datalen = 0x05;
+ buffer_copy(&g_buffer, &datalen, sizeof(datalen));
+
+ u8value = 0xf4; //
+ buffer_copy(&g_buffer, &u8value, sizeof(u8value));
+
+ mtmsi = htonl(g_tauRespInfo->ue_idx);
+ buffer_copy(&g_buffer, &(mtmsi), sizeof(mtmsi));
+#endif
+ /* NAS PDU end */
+
+ /* Calculate mac */
+ uint8_t direction = 1;
+ uint8_t bearer = 0;
+
+ calculate_mac(g_tauRespInfo->int_key, nas_hdr->seq_no,
+ direction, bearer, &g_buffer.buf[mac_data_pos],
+ g_buffer.pos - mac_data_pos,
+ &g_buffer.buf[mac_data_pos - MAC_SIZE]);
+
+
+ /* Copy nas length to nas length field */
+ datalen = g_buffer.pos - nas_len_pos - 1;
+ memcpy(&g_buffer.buf[nas_len_pos], &datalen, sizeof(datalen));
+
+ /* Copy nas length to nas length field */
+ datalen = g_buffer.pos - nas_len_pos - 2;
+ memcpy(&(g_buffer.buf[nas_len_pos + 1]), &datalen, sizeof(datalen));
+
+ /* Copy length to s1ap length field */
+ datalen = g_buffer.pos - s1ap_len_pos - 1;
+ memcpy(g_buffer.buf + s1ap_len_pos, &datalen, sizeof(datalen));
+
+ send_sctp_msg(g_tauRespInfo->enb_fd, g_buffer.buf, g_buffer.pos,1);
+ log_msg(LOG_INFO, "\nTAU RESP received from MME\n");
+ return SUCCESS;
+}
+
+
+void*
+tau_response_handler(void *data)
+{
+
+ log_msg(LOG_INFO, "TAU response handler ready.\n");
+
+ tau_rsp_processing((struct tauResp_Q_msg *)data);
+
+ return NULL;
+}