blob: b0e8c1f683fcb146e52e8e51a11cd7c87c63c0cc [file] [log] [blame]
anjana_sreekumar@infosys.com991c2062020-01-08 11:42:57 +05301/*
2 * Copyright (c) 2003-2018, Great Software Laboratory Pvt. Ltd.
3 * Copyright (c) 2017 Intel Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#include <stdio.h>
19#include <stdlib.h>
20#include <pthread.h>
21#include <string.h>
22#include <unistd.h>
23#include <stdint.h>
24
25#include "log.h"
26#include "err_codes.h"
27#include "message_queues.h"
28#include "ipc_api.h"
29#include "s1ap.h"
30#include "s1ap_config.h"
31#include "main.h"
32#include "msgType.h"
33
34static int
35get_detach_accept_protoie_value(struct proto_IE *value, struct detach_accept_Q_msg *g_acptReqInfo)
36{
37 uint8_t ieCnt = 0;
38
39 value->no_of_IEs = DTCH_ACCEPT_NO_OF_IES;
40
41 value->data = (proto_IEs *) malloc(DTCH_ACCEPT_NO_OF_IES *
42 sizeof(proto_IEs));
43
44 value->data[ieCnt].val.mme_ue_s1ap_id = g_acptReqInfo->ue_idx;
45 ieCnt++;
46
47 value->data[ieCnt].val.enb_ue_s1ap_id = g_acptReqInfo->enb_s1ap_ue_id;
48 ieCnt++;
49
50 struct nasPDU *nas = &(value->data[ieCnt].val.nas);
51 nas->header.security_header_type = IntegrityProtectedCiphered;
52 nas->header.proto_discriminator = EPSMobilityManagementMessages;
53
54 /* placeholder for mac. mac value will be calculated later */
55 uint8_t mac[MAC_SIZE] = {0};
56 memcpy(nas->header.mac, mac, MAC_SIZE);
57
58 nas->header.seq_no = g_acptReqInfo->dl_seq_no;
59 nas->header.message_type = DetachAccept;
60
61 ieCnt++;
62
63 return SUCCESS;
64}
65
66/**
67* Stage specific message processing.
68*/
69static int
70detach_accept_processing(struct detach_accept_Q_msg *g_acptReqInfo)
71{
72 unsigned char tmpStr[4];
73 struct s1ap_PDU s1apPDU= {0};
74 uint16_t protocolIe_Id;
75 uint8_t protocolIe_criticality = CRITICALITY_REJECT;
76 uint8_t initiating_msg = 0;
77 uint8_t datalen = 0;
78 uint8_t s1ap_len_pos;
79 uint8_t nas_len_pos;
80 uint8_t u8value = 0;
81 uint8_t mac_data_pos;
82
83 Buffer g_acpt_buffer;
84
85 s1apPDU.procedurecode = id_downlinkNASTransport;
86 s1apPDU.criticality = CRITICALITY_IGNORE;
87
88 get_detach_accept_protoie_value(&s1apPDU.value, g_acptReqInfo);
89
90 g_acpt_buffer.pos = 0;
91
92 buffer_copy(&g_acpt_buffer, &initiating_msg,
93 sizeof(initiating_msg));
94
95 buffer_copy(&g_acpt_buffer, &s1apPDU.procedurecode,
96 sizeof(s1apPDU.procedurecode));
97
98 buffer_copy(&g_acpt_buffer, &s1apPDU.criticality,
99 sizeof(s1apPDU.criticality));
100
101 s1ap_len_pos = g_acpt_buffer.pos;
102
103 /* length of Detach Accept */
104 u8value = 0;
105 buffer_copy(&g_acpt_buffer, &u8value, sizeof(u8value));
106
107 /* TODO remove hardcoded values */
108 uint8_t chProtoIENo[3] = {0,0,3};
109 buffer_copy(&g_acpt_buffer, chProtoIENo, 3);
110
111 /* id-MME-UE-S1AP-ID */
112 protocolIe_Id = id_MME_UE_S1AP_ID;
113 copyU16(tmpStr, protocolIe_Id);
114 buffer_copy(&g_acpt_buffer, tmpStr, sizeof(protocolIe_Id));
115 buffer_copy(&g_acpt_buffer, &protocolIe_criticality,
116 sizeof(protocolIe_criticality));
117 datalen = 2;
118 /* TODO need to add proper handling*/
119 unsigned char mme_ue_id[3];
120 datalen = copyU16(mme_ue_id, s1apPDU.value.data[0].val.mme_ue_s1ap_id);
121 buffer_copy(&g_acpt_buffer, &datalen, sizeof(datalen));
122 buffer_copy(&g_acpt_buffer, mme_ue_id, datalen);
123
124 /* id-eNB-UE-S1AP-ID */
125 protocolIe_Id = id_eNB_UE_S1AP_ID;
126 copyU16(tmpStr, protocolIe_Id);
127 buffer_copy(&g_acpt_buffer, tmpStr, sizeof(protocolIe_Id));
128 buffer_copy(&g_acpt_buffer, &protocolIe_criticality,
129 sizeof(protocolIe_criticality));
130 /* TODO needs proper handling*/
131 unsigned char enb_ue_id[3];
132 datalen = copyU16(enb_ue_id, s1apPDU.value.data[1].val.enb_ue_s1ap_id);
133 buffer_copy(&g_acpt_buffer, &datalen, sizeof(datalen));
134 buffer_copy(&g_acpt_buffer, enb_ue_id, datalen);
135
136 /* NAS PDU start */
137 protocolIe_Id = id_NAS_PDU;
138 copyU16(tmpStr, protocolIe_Id);
139 buffer_copy(&g_acpt_buffer, tmpStr, sizeof(protocolIe_Id));
140 buffer_copy(&g_acpt_buffer, &protocolIe_criticality,
141 sizeof(protocolIe_criticality));
142
143 nas_len_pos = g_acpt_buffer.pos;
144
145 datalen = 0;
146 buffer_copy(&g_acpt_buffer, &datalen, sizeof(datalen));
147
148 buffer_copy(&g_acpt_buffer, &datalen, sizeof(datalen));
149
150 nas_pdu_header *nas_hdr = &(s1apPDU.value.data[2].val.nas.header);
151
152 /* security header and protocol discriminator */
153 u8value = (nas_hdr->security_header_type << 4 |
154 nas_hdr->proto_discriminator);
155 buffer_copy(&g_acpt_buffer, &u8value, sizeof(u8value));
156
157 /* mac */
158 /* placeholder for mac. mac value will be calculated later */
159 buffer_copy(&g_acpt_buffer, nas_hdr->mac, MAC_SIZE);
160 mac_data_pos = g_acpt_buffer.pos;
161
162 /* sequence number */
163 buffer_copy(&g_acpt_buffer, &(nas_hdr->seq_no),
164 sizeof(nas_hdr->seq_no));
165
166 /* security header and protocol discriminator */
167 nas_hdr->security_header_type = Plain;
168 u8value = (nas_hdr->security_header_type << 4 |
169 nas_hdr->proto_discriminator);
170 buffer_copy(&g_acpt_buffer, &u8value, sizeof(u8value));
171
172 /* message type */
173 buffer_copy(&g_acpt_buffer, &(nas_hdr->message_type),
174 sizeof(nas_hdr->message_type));
175
176 /* NAS PDU end */
177
178 /* Calculate mac */
179 uint8_t direction = 1;
180 uint8_t bearer = 0;
181
182 calculate_mac(g_acptReqInfo->int_key, nas_hdr->seq_no,
183 direction, bearer, &g_acpt_buffer.buf[mac_data_pos],
184 g_acpt_buffer.pos - mac_data_pos,
185 &g_acpt_buffer.buf[mac_data_pos - MAC_SIZE]);
186
187 /* Copy nas length to nas length field */
188 datalen = g_acpt_buffer.pos - nas_len_pos -1;
189 memcpy(&(g_acpt_buffer.buf[nas_len_pos]), &datalen, sizeof(datalen));
190
191 /* Copy nas length to nas length field */
192 datalen = g_acpt_buffer.pos - nas_len_pos - 2;
193 memcpy(&(g_acpt_buffer.buf[nas_len_pos + 1]), &datalen, sizeof(datalen));
194
195 /* Copy length to s1ap length field */
196 datalen = g_acpt_buffer.pos - s1ap_len_pos - 1;
197 memcpy(g_acpt_buffer.buf + s1ap_len_pos, &datalen, sizeof(datalen));
198
199 /* TODO: temp fix */
200 //g_ics_buffer.buf[1] = 0x09;
201 send_sctp_msg(g_acptReqInfo->enb_fd, g_acpt_buffer.buf, g_acpt_buffer.pos,1);
202
203 log_msg(LOG_INFO, "Detach Accept sent to UE.");
204
205 return SUCCESS;
206}
207
208/**
209* essage processing for ue context release
210*/
211static int
212ue_ctx_release_processing(struct detach_accept_Q_msg *g_acptReqInfo)
213{
214 Buffer g_ctxrel_buffer;
215 unsigned char tmpStr[4];
216 struct s1ap_PDU s1apPDU;
217 uint16_t protocolIe_Id;
218 uint8_t protocolIe_criticality = CRITICALITY_REJECT;
219 uint8_t initiating_msg = 0;
220 uint8_t datalen = 0;
221 uint8_t s1ap_len_pos;
222 uint8_t u8value = 0;
223
224 s1apPDU.procedurecode = id_UEContexRelease;
225 s1apPDU.criticality = CRITICALITY_IGNORE;
226
227 g_ctxrel_buffer.pos = 0;
228
229 buffer_copy(&g_ctxrel_buffer, &initiating_msg,
230 sizeof(initiating_msg));
231
232 buffer_copy(&g_ctxrel_buffer, &s1apPDU.procedurecode,
233 sizeof(s1apPDU.procedurecode));
234
235 buffer_copy(&g_ctxrel_buffer, &s1apPDU.criticality,
236 sizeof(s1apPDU.criticality));
237
238 s1ap_len_pos = g_ctxrel_buffer.pos;
239
240 /* length of UE Context Release */
241 u8value = 0;
242 buffer_copy(&g_ctxrel_buffer, &u8value, sizeof(u8value));
243
244 /* TODO remove hardcoded values */
245 uint8_t chProtoIENo[3] = {0,0,2};
246 buffer_copy(&g_ctxrel_buffer, chProtoIENo, 3);
247
248 /* id-UE-S1AP-IDs */
249 protocolIe_Id = id_UE_S1AP_IDs;
250 copyU16(tmpStr, protocolIe_Id);
251 buffer_copy(&g_ctxrel_buffer, tmpStr, sizeof(protocolIe_Id));
252 buffer_copy(&g_ctxrel_buffer, &protocolIe_criticality,
253 sizeof(protocolIe_criticality));
254
255 uint8_t mme_ue_id[4];
256 uint8_t mme_ue_id_len = copyU16(mme_ue_id,
257 s1apPDU.value.data[0].val.mme_ue_s1ap_id);
258
259 if (mme_ue_id[0] == 0x40 || mme_ue_id[0] == 0x80)
260 mme_ue_id[0] = ((mme_ue_id[0] & 0x0F)<<4 |
261 (mme_ue_id[0] & 0xF0)>>4);
262
263 uint8_t enb_ue_id[4];
264 uint8_t enb_ue_id_len = copyU16(enb_ue_id,
265 s1apPDU.value.data[1].val.enb_ue_s1ap_id);
266
267 datalen = mme_ue_id_len + enb_ue_id_len;
268 buffer_copy(&g_ctxrel_buffer, &datalen, sizeof(datalen));
269 buffer_copy(&g_ctxrel_buffer, mme_ue_id, mme_ue_id_len);
270 buffer_copy(&g_ctxrel_buffer, enb_ue_id, enb_ue_id_len);
271
272#if 0
273 /* id-MME-UE-S1AP-ID */
274 protocolIe_Id = id_MME_UE_S1AP_ID;
275 copyU16(tmpStr, protocolIe_Id);
276 buffer_copy(&g_ctxrel_buffer, tmpStr,
277 sizeof(protocolIe_Id));
278
279 protocolIe_criticality = CRITICALITY_REJECT;
280 buffer_copy(&g_ctxrel_buffer, &protocolIe_criticality,
281 sizeof(protocolIe_criticality));
282
283 datalen = 2;
284
285 /* TODO needs proper handling*/
286 unsigned char mme_ue_id[4];
287 datalen = copyU16(mme_ue_id, s1apPDU.value.data[0].val.mme_ue_s1ap_id);
288 buffer_copy(&g_ctxrel_buffer, &datalen, sizeof(datalen));
289 buffer_copy(&g_ctxrel_buffer, mme_ue_id, datalen);
290#endif
291
292 /* id-Cause */
293 protocolIe_Id = id_Cause;
294 protocolIe_criticality = CRITICALITY_IGNORE;
295 copyU16(tmpStr, protocolIe_Id);
296 buffer_copy(&g_ctxrel_buffer, tmpStr, sizeof(protocolIe_Id));
297 buffer_copy(&g_ctxrel_buffer, &protocolIe_criticality,
298 sizeof(protocolIe_criticality));
299 datalen = 1;
300 buffer_copy(&g_ctxrel_buffer, &datalen, sizeof(datalen));
301 /* TODO : Revisit. cause : nas(2) and value : detach (2), why 0x24 ? */
302 u8value = 0x24;
303 buffer_copy(&g_ctxrel_buffer, &u8value, sizeof(u8value));
304
305 /* Copy length to s1ap length field */
306 datalen = g_ctxrel_buffer.pos - s1ap_len_pos - 1;
307 memcpy(g_ctxrel_buffer.buf + s1ap_len_pos, &datalen, sizeof(datalen));
308 send_sctp_msg(g_acptReqInfo->enb_fd, g_ctxrel_buffer.buf, g_ctxrel_buffer.pos,1);
309
310 log_msg(LOG_INFO,"S1 Release sent to UE");
311
312 return SUCCESS;
313}
314
315/**
316* Thread function for stage.
317*/
318void*
319detach_accept_handler(void *data)
320{
321 log_msg(LOG_INFO, "detach accept handler ready.\n");
322 struct detach_accept_Q_msg *msg = (struct detach_accept_Q_msg *)data;
323
324 detach_accept_processing(msg);
325 ue_ctx_release_processing(msg);
326
327 return NULL;
328}