blob: 8838da3d0d7f9c8aa71a3bf435985dddbad97004 [file] [log] [blame]
anjana_sreekumar@infosys.com991c2062020-01-08 11:42:57 +05301/*
2 * Copyright 2019-present Open Networking Foundation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 */
7#include <stdio.h>
8#include <stdlib.h>
9#include <pthread.h>
10#include <string.h>
11#include <unistd.h>
12#include <stdint.h>
13
14
15
16#include "log.h"
17#include "err_codes.h"
18#include "options.h"
19#include "ipc_api.h"
20#include "main.h"
21#include "s1ap.h"
22#include "s1ap_config.h"
23#include "sctp_conn.h"
24#include "s1ap_structs.h"
25#include "s1ap_msg_codes.h"
26#include "msgType.h"
27extern s1ap_config g_s1ap_cfg;
28extern ipc_handle ipc_S1ap_Hndl;
29static Buffer g_buffer;
30static int
31get_tau_rsp_protoie_value(struct proto_IE *value, struct tauResp_Q_msg *g_tauRespInfo)
32{
33
34 value->no_of_IEs = TAU_RSP_NO_OF_IES;
35
36 value->data = (proto_IEs *) malloc(TAU_RSP_NO_OF_IES*
37 sizeof(proto_IEs));
38
39 value->data[0].val.mme_ue_s1ap_id = g_tauRespInfo->ue_idx;
40 value->data[1].val.enb_ue_s1ap_id = g_tauRespInfo->s1ap_enb_ue_id;
41
42 log_msg(LOG_INFO, "mme_ue_s1ap_id %d and enb_ue_s1ap_id %d\n",
43 g_tauRespInfo->ue_idx, g_tauRespInfo->s1ap_enb_ue_id);
44
45 /* TODO: Add enum for security header type */
46 value->data[2].val.nas.header.security_header_type = IntegrityProtectedCiphered;
47 value->data[2].val.nas.header.proto_discriminator = EPSMobilityManagementMessages;
48 if(g_tauRespInfo->status == 0)
49 value->data[2].val.nas.header.message_type = TauAccept;
50 else
51 value->data[2].val.nas.header.message_type = TauReject;
52 value->data[2].val.nas.header.nas_security_param = 0;
53 /* placeholder for mac. mac value will be calculated later */
54 uint8_t mac[MAC_SIZE] = {0};
55 memcpy(value->data[2].val.nas.header.mac, mac, MAC_SIZE);
56 value->data[2].val.nas.header.seq_no = g_tauRespInfo->dl_seq_no;
57 value->data[2].val.nas.header.eps_bearer_identity = 0;
58 value->data[2].val.nas.header.procedure_trans_identity = 1;
59 value->data[2].val.nas.elements_len = TAU_RSP_NO_OF_NAS_IES;
60 value->data[2].val.nas.elements = (nas_pdu_elements *) malloc(TAU_RSP_NO_OF_NAS_IES * sizeof(nas_pdu_elements));
61 nas_pdu_elements *nasIEs = value->data[2].val.nas.elements;
62 uint8_t nasIeCnt = 0;
63 nasIEs[nasIeCnt].pduElement.eps_res = 0; /* TA updated */
64 nasIeCnt++;
65 nasIEs[nasIeCnt].pduElement.spare = 0; /* TA updated */
66 nasIeCnt++;
67
68 return SUCCESS;
69}
70
71static int
72tau_rsp_processing(struct tauResp_Q_msg *g_tauRespInfo)
73{
74
75 struct s1ap_PDU s1apPDU= {0};
76
77 uint8_t nas_len_pos;
78 uint8_t s1ap_len_pos;
79 uint8_t mac_data_pos;
80 uint8_t datalen;
81 uint8_t u8value;
82
83 if(g_tauRespInfo->status != 0)
84 {
85 /* Assigning values to s1apPDU */
86 s1apPDU.procedurecode = id_errorIndication;
87 s1apPDU.criticality = CRITICALITY_IGNORE;
88 get_tau_rsp_protoie_value(&s1apPDU.value,g_tauRespInfo);
89 g_buffer.pos = 0;
90
91 uint8_t initiating_message = 0; /* TODO: Add enum */
92 buffer_copy(&g_buffer, &initiating_message,
93 sizeof(initiating_message));
94
95 buffer_copy(&g_buffer, &s1apPDU.procedurecode,
96 sizeof(s1apPDU.procedurecode));
97
98 buffer_copy(&g_buffer, &s1apPDU.criticality,
99 sizeof(s1apPDU.criticality));
100
101 s1ap_len_pos = g_buffer.pos;
102
103 /* length of S1ap message */
104 u8value = 0;
105 buffer_copy(&g_buffer, &u8value, sizeof(u8value));
106
107 /* TODO remove hardcoded values */
108 unsigned char chProtoIENo[3] = {0,0,2};
109
110 buffer_copy(&g_buffer, chProtoIENo, 3);
111
112 unsigned char tmpStr[4];
113
114 /* id-eNB-UE-S1AP-ID */
115
116 uint16_t protocolIe_Id = id_eNB_UE_S1AP_ID;
117 uint8_t protocolIe_criticality = CRITICALITY_REJECT;
118 copyU16(tmpStr, protocolIe_Id);
119 buffer_copy(&g_buffer, tmpStr,
120 sizeof(protocolIe_Id));
121
122 buffer_copy(&g_buffer, &protocolIe_criticality,
123 sizeof(protocolIe_criticality));
124
125
126 /* TODO needs proper handling*/
127 unsigned char enb_ue_id[3];
128 datalen = copyU16(enb_ue_id,
129 s1apPDU.value.data[1].val.enb_ue_s1ap_id);
130 buffer_copy(&g_buffer, &datalen, sizeof(datalen));
131 buffer_copy(&g_buffer, enb_ue_id, datalen);
132
133 unsigned char cause[6] = {0,2,40,2,4, 0};
134 buffer_copy(&g_buffer, cause, sizeof(cause));
135
136 /* Copy length to s1ap length field */
137 datalen = g_buffer.pos - s1ap_len_pos - 1;
138 memcpy(g_buffer.buf + s1ap_len_pos, &datalen, sizeof(datalen));
139 return E_FAIL;
140 }
141 /* Assigning values to s1apPDU */
142 s1apPDU.procedurecode = id_downlinkNASTransport;
143 s1apPDU.criticality = CRITICALITY_IGNORE;
144
145 get_tau_rsp_protoie_value(&s1apPDU.value,g_tauRespInfo);
146
147 /* Copy values to buffer from s1apPDU */
148
149 g_buffer.pos = 0;
150
151 uint8_t initiating_message = 0; /* TODO: Add enum */
152 buffer_copy(&g_buffer, &initiating_message,
153 sizeof(initiating_message));
154
155 buffer_copy(&g_buffer, &s1apPDU.procedurecode,
156 sizeof(s1apPDU.procedurecode));
157
158 buffer_copy(&g_buffer, &s1apPDU.criticality,
159 sizeof(s1apPDU.criticality));
160
161 s1ap_len_pos = g_buffer.pos;
162
163 /* length of S1ap message */
164 u8value = 0;
165 buffer_copy(&g_buffer, &u8value, sizeof(u8value));
166
167 /* TODO remove hardcoded values */
168 unsigned char chProtoIENo[3] = {0,0,3};
169
170 buffer_copy(&g_buffer, chProtoIENo, 3);
171
172 unsigned char tmpStr[4];
173
174 /* id-MME-UE-S1AP-ID */
175 uint16_t protocolIe_Id = id_MME_UE_S1AP_ID;
176 copyU16(tmpStr, protocolIe_Id);
177 buffer_copy(&g_buffer, tmpStr,
178 sizeof(protocolIe_Id));
179
180 uint8_t protocolIe_criticality = CRITICALITY_REJECT;
181 buffer_copy(&g_buffer, &protocolIe_criticality,
182 sizeof(protocolIe_criticality));
183
184 /* TODO needs proper handling*/
185 unsigned char mme_ue_id[3];
186 datalen = copyU16(mme_ue_id,
187 s1apPDU.value.data[0].val.mme_ue_s1ap_id);
188 buffer_copy(&g_buffer, &datalen, sizeof(datalen));
189 buffer_copy(&g_buffer, mme_ue_id, datalen);
190
191 /* id-eNB-UE-S1AP-ID */
192
193 protocolIe_Id = id_eNB_UE_S1AP_ID;
194 copyU16(tmpStr, protocolIe_Id);
195 buffer_copy(&g_buffer, tmpStr,
196 sizeof(protocolIe_Id));
197
198 buffer_copy(&g_buffer, &protocolIe_criticality,
199 sizeof(protocolIe_criticality));
200
201 /* TODO needs proper handling*/
202 unsigned char enb_ue_id[3];
203 datalen = copyU16(enb_ue_id,
204 s1apPDU.value.data[1].val.enb_ue_s1ap_id);
205 buffer_copy(&g_buffer, &datalen, sizeof(datalen));
206 buffer_copy(&g_buffer, enb_ue_id, datalen);
207
208 /* id-NAS-PDU */
209 protocolIe_Id = id_NAS_PDU;
210 copyU16(tmpStr, protocolIe_Id);
211 buffer_copy(&g_buffer, tmpStr,
212 sizeof(protocolIe_Id));
213 buffer_copy(&g_buffer, &protocolIe_criticality,
214 sizeof(protocolIe_criticality));
215
216 nas_len_pos = g_buffer.pos;
217 datalen = 0;
218 buffer_copy(&g_buffer, &datalen, sizeof(datalen));
219 buffer_copy(&g_buffer, &datalen, sizeof(datalen));
220
221 struct nasPDU *nas = &(s1apPDU.value.data[2].val.nas);
222 struct nas_pdu_header *nas_hdr = &(s1apPDU.value.data[2].val.nas.header);
223
224 u8value = (nas->header.security_header_type << 4) |
225 nas->header.proto_discriminator;
226 buffer_copy(&g_buffer, &u8value, sizeof(u8value));
227
228 /* mac */
229 /* placeholder for mac. mac value will be calculated later */
230 buffer_copy(&g_buffer, nas_hdr->mac, MAC_SIZE);
231 mac_data_pos = g_buffer.pos;
232
233 /* sequence number */
234 buffer_copy(&g_buffer, &(nas_hdr->seq_no),
235 sizeof(nas_hdr->seq_no));
236
237 /* security header and protocol discriminator */
238 nas_hdr->security_header_type = Plain;
239 u8value = (0 << 4 | nas_hdr->proto_discriminator);
240 buffer_copy(&g_buffer, &u8value, sizeof(u8value));
241
242 /* message type */
243 buffer_copy(&g_buffer, &nas->header.message_type,
244 sizeof(nas->header.message_type));
245
246
247 u8value = 0;
248 buffer_copy(&g_buffer, &u8value, sizeof(u8value));
249 u8value = 0x5a;
250 buffer_copy(&g_buffer, &u8value, sizeof(u8value));
251#define DISABLE_TAU 0
252#if DISABLE_TAU
253 u8value = 0xe0;
254#else
255 u8value = 0x21;
256#endif
257 buffer_copy(&g_buffer, &u8value, sizeof(u8value));
258
259#if 1
260 /* adding GUTI */
261 u8value = 0x50; /* element id TODO: define macro or enum */
262 buffer_copy(&g_buffer, &u8value, sizeof(u8value));
263 datalen = 11;
264 buffer_copy(&g_buffer, &datalen, sizeof(datalen));
265 u8value = 246; /* TODO: remove hard coding */
266 buffer_copy(&g_buffer, &u8value, sizeof(u8value));
267
268 unsigned char x3 = g_tauRespInfo->tai.plmn_id.idx[2];
269 unsigned char x2 = g_tauRespInfo->tai.plmn_id.idx[1];
270 unsigned char x31 = x3 >> 4;
271 unsigned char x32 = x3 & 0xf;
272 unsigned char x21 = x2 >> 4;
273 unsigned char x22 = x2 & 0xf;
274 x3 = x21 | (x32 <<4);
275 x2 = (x31 << 4) | x22;
276 g_tauRespInfo->tai.plmn_id.idx[1] = x2;
277 g_tauRespInfo->tai.plmn_id.idx[2] = x3;
278
279 buffer_copy(&g_buffer, &g_tauRespInfo->tai.plmn_id, 3);
280
281 uint16_t grpid = htons(g_s1ap_cfg.mme_group_id);
282 buffer_copy(&g_buffer, &grpid, sizeof(grpid));
283
284 u8value = g_s1ap_cfg.mme_code;
285 buffer_copy(&g_buffer, &u8value, sizeof(u8value));
286
287 uint32_t mtmsi = htonl(g_tauRespInfo->m_tmsi);
288 buffer_copy(&g_buffer, &(mtmsi), sizeof(mtmsi));
289#endif
290
291
292
293#if 1
294 /*TODO : Experiment */
295 u8value = 0x23; /* element id TODO: define macro or enum */
296 buffer_copy(&g_buffer, &u8value, sizeof(u8value));
297 datalen = 0x05;
298 buffer_copy(&g_buffer, &datalen, sizeof(datalen));
299
300 u8value = 0xf4; //
301 buffer_copy(&g_buffer, &u8value, sizeof(u8value));
302
303 mtmsi = htonl(g_tauRespInfo->ue_idx);
304 buffer_copy(&g_buffer, &(mtmsi), sizeof(mtmsi));
305#endif
306 /* NAS PDU end */
307
308 /* Calculate mac */
309 uint8_t direction = 1;
310 uint8_t bearer = 0;
311
312 calculate_mac(g_tauRespInfo->int_key, nas_hdr->seq_no,
313 direction, bearer, &g_buffer.buf[mac_data_pos],
314 g_buffer.pos - mac_data_pos,
315 &g_buffer.buf[mac_data_pos - MAC_SIZE]);
316
317
318 /* Copy nas length to nas length field */
319 datalen = g_buffer.pos - nas_len_pos - 1;
320 memcpy(&g_buffer.buf[nas_len_pos], &datalen, sizeof(datalen));
321
322 /* Copy nas length to nas length field */
323 datalen = g_buffer.pos - nas_len_pos - 2;
324 memcpy(&(g_buffer.buf[nas_len_pos + 1]), &datalen, sizeof(datalen));
325
326 /* Copy length to s1ap length field */
327 datalen = g_buffer.pos - s1ap_len_pos - 1;
328 memcpy(g_buffer.buf + s1ap_len_pos, &datalen, sizeof(datalen));
329
330 send_sctp_msg(g_tauRespInfo->enb_fd, g_buffer.buf, g_buffer.pos,1);
331 log_msg(LOG_INFO, "\nTAU RESP received from MME\n");
332 return SUCCESS;
333}
334
335
336void*
337tau_response_handler(void *data)
338{
339
340 log_msg(LOG_INFO, "TAU response handler ready.\n");
341
342 tau_rsp_processing((struct tauResp_Q_msg *)data);
343
344 return NULL;
345}