blob: 735652c4f3a77b1615f9dc1a688059c21b47046b [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
19#include <stdio.h>
20#include <stdlib.h>
21#include <unistd.h>
22#include <string.h>
23#include <pthread.h>
24
25#include "options.h"
26#include "ipc_api.h"
27#include "main.h"
28#include "s1ap.h"
29#include "s1ap_config.h"
30#include "sctp_conn.h"
31#include "s1ap_structs.h"
32#include "s1ap_msg_codes.h"
33#include "s1ap_ie.h"
34#include "ProtocolIE-ID.h"
35#include "ProtocolIE-Field.h"
36static void
37parse_erab_pdu(char *msg, int nas_msg_len, struct eRAB_elements *erab)
38{
39 //struct eRAB_header *header = (struct eRAB*)msg;
40
41 //char *ie = msg + 5; /*ID(2)+crit(1)+len(1)+mistry(1)*/
42
43 /*TODO: write parse_IEs for erab IEs here going ahead*/
44 /*For now copying directly as it is single structure*/
45 char *ie = msg + 5; /*ID(2)+crit(1)+len(1)*/
46
47 erab->no_of_elements = 1;
48 erab->elements = (union eRAB_IE*)calloc(sizeof(union eRAB_IE), 1);
49 if(NULL == erab->elements) {
50 log_msg(LOG_ERROR, "Memory alloc failed\n");
51 exit(-1);
52 }
53
54 erab->elements[0].su_res.eRAB_id = *ie;
55 ++ie;
56 ++ie; //what is this identify.
57 memcpy(&(erab->elements[0].su_res.transp_layer_addr), ie, sizeof(unsigned int));
58 erab->elements[0].su_res.transp_layer_addr = ntohl(erab->elements[0].su_res.transp_layer_addr);
59 log_msg(LOG_INFO, "eRAB - Transport layer address : %d\n", erab->elements[0].su_res.transp_layer_addr);
60 //ntohl ??
61 ie+=sizeof(unsigned int);
62
63 memcpy(&(erab->elements[0].su_res.gtp_teid), ie, sizeof(unsigned int));
64 erab->elements[0].su_res.gtp_teid = ntohl(erab->elements[0].su_res.gtp_teid);
65 log_msg(LOG_INFO, "eRAB - Teid : %d\n", erab->elements[0].su_res.gtp_teid);
66 //ntohl ??
67}
68
69void
70parse_nas_pdu(char *msg, int nas_msg_len, struct nasPDU *nas,
71 unsigned short proc_code)
72{
73 log_msg(LOG_INFO, "NAS PDU proc code: %u\n", proc_code);
74
75 unsigned short msg_len = nas_msg_len;
76 char* msg_end = msg + nas_msg_len;
77
78 char *buffer = NULL;
79 log_msg(LOG_INFO, "NAS PDU msg: %s\n", msg_to_hex_str(msg, msg_len, &buffer));
80 log_buffer_free(&buffer);
81
82#if 0
83 if(S1AP_UL_NAS_TX_MSG_CODE == proc_code) {
84 /*check whether there is security header*/
85 unsigned char header_type;
86 memcpy(&header_type, msg+1, 1);
87 header_type >>= 4;
88 if(0 == header_type) { /*not security header*/
89 log_msg(LOG_INFO, "No security header\n");
90 memcpy(&(nas->header), msg+1, 2);/*copy only till msg type*/
91 } else {
92 log_msg(LOG_INFO, "Security header\n");
93 /*now for esm resp, there is procedure tx identity, why the hell it was not there before.*/
94 /*one more donkey logic, do something!!*/
95 if(4 == header_type || ((7 == (*(msg+7) & 7)))) {
96 memcpy(&(nas->header), msg+7, 2);/*copy only till msg type*/
97 offset = 9;
98 } else {
99 unsigned char tmp;
100 memcpy(&(nas->header.message_type), msg+9, 1);/*copy only till msg type*/
101 memcpy(&(tmp), msg+7, 1);/*copy only till msg type*/
102 nas->header.security_header_type = tmp;
103 offset = 10;
104 }
105 }
106 } else {
107 memcpy(&(nas->header), msg+2, sizeof(nas_pdu_header));
108 }
109
110 if(S1AP_UL_NAS_TX_MSG_CODE == proc_code) {
111 /*check whether there is security header*/
112 unsigned char header_type = 0;
113
114 memcpy(&header_type, msg+1, 1);
115 header_type >>= 4;
116 if(0 == header_type) { /*not security header*/
117 log_msg(LOG_INFO, "No security header\n");
118 memcpy(&(nas->header), msg+1, 2);/*copy only till msg type*/
119 } else {
120 log_msg(LOG_INFO, "Security header\n");
121 /*now for esm resp, there is procedure tx identity, why the hell it was not there before.*/
122 /*one more donkey logic, do something!!*/
123 if(4 == header_type || ((7 == (*(msg+7) & 7)))) {
124 log_msg(LOG_INFO, "header == 4 || 7\n");
125 if(header_type == 4 || header_type == 2) {
126 log_msg(LOG_INFO, "security - cihpered\n");
127 memcpy(&(nas->header), msg+7, 2);/*copy only till msg type*/
128 offset = 9;
129 }
130 else {
131 log_msg(LOG_INFO, "security - noned\n");
132 memcpy(&(nas->header), msg+1, 2);/*copy only till msg type*/
133 offset = 3;
134 }
135 } else {
136 unsigned char tmp;
137 memcpy(&(nas->header.message_type), msg+9, 1);/*copy only till msg type*/
138 memcpy(&(tmp), msg+7, 1);/*copy only till msg type*/
139 nas->header.security_header_type = tmp;
140 offset = 10;
141 }
142 }
143 } else if (S1AP_INITIAL_UE_MSG_CODE == proc_code ) {
144#endif
145
146 nas_pdu_header_sec nas_header_sec;
147 nas_pdu_header_short nas_header_short;
148 nas_pdu_header_long nas_header_long;
149
150 unsigned char sec_header_type;
151 unsigned char protocol_discr;
152
153 sec_header_type = (msg[0] >> 4) & 0x0F;
154 protocol_discr = msg[0] & 0x0F;
155 unsigned char is_ESM = ((unsigned short)protocol_discr == 0x02); // see TS 24.007
156 log_msg(LOG_INFO, "Security header=%d\n", sec_header_type);
157 log_msg(LOG_INFO, "Protocol discriminator=%d\n", protocol_discr);
158 log_msg(LOG_INFO, "is_ESM=%d\n", is_ESM);
159
160 if(0 != sec_header_type) { /*security header*/
161 log_msg(LOG_INFO, "Security header\n");
162 if(SERVICE_REQ_SECURITY_HEADER == sec_header_type)
163 {
164 log_msg(LOG_INFO, "Recvd security header for Service request.");
165 nas->header.security_header_type = sec_header_type;
166 nas->header.proto_discriminator = protocol_discr;
167 msg += 1;
168 nas->header.ksi = msg[0] >> 4;
169 nas->header.seq_no = msg[0] & 0x0F;
170 msg += 1;
171 memcpy(nas->header.short_mac, msg, SHORT_MAC_SIZE);
172 nas->header.message_type = NAS_SERVICE_REQUEST;
173 return;
174 }
175
176 memcpy(&nas_header_sec, msg, sizeof(nas_pdu_header_sec));
177
178 char *buffer = NULL;
179 log_msg(LOG_INFO, "mac=%s\n", msg_to_hex_str((char *)nas_header_sec.mac, MAC_SIZE, &buffer));
180 log_buffer_free(&buffer);
181
182 log_msg(LOG_INFO, "seq no=%x\n", nas_header_sec.seq_no);
183 nas->header.seq_no = nas_header_sec.seq_no;
184 msg += 6;
185
186 sec_header_type = msg[0] >> 4;
187 protocol_discr = msg[0] & 0x0F;
188 unsigned char is_ESM = ((unsigned short)protocol_discr == 0x02); // see TS 24.007
189 log_msg(LOG_INFO, "Security header=%d\n", sec_header_type);
190 log_msg(LOG_INFO, "Protocol discriminator=%d\n", protocol_discr);
191 log_msg(LOG_INFO, "is_ESM=%d\n", is_ESM);
192 if (is_ESM) {
193 log_msg(LOG_INFO, "NAS PDU is ESM\n");
194 memcpy(&nas_header_long, msg, sizeof(nas_header_long)); /*copy only till msg type*/
195 msg += 3;
196
197 nas->header.security_header_type = nas_header_long.security_header_type;
198 nas->header.proto_discriminator = nas_header_long.proto_discriminator;
199 nas->header.procedure_trans_identity = nas_header_long.procedure_trans_identity;
200 nas->header.message_type = nas_header_long.message_type;
201 } else {
202 log_msg(LOG_INFO, "NAS PDU is EMM\n");
203 memcpy(&nas_header_short, msg, sizeof(nas_header_short)); /*copy only till msg type*/
204 msg += 2;
205
206 nas->header.security_header_type = nas_header_short.security_header_type;
207 nas->header.proto_discriminator = nas_header_short.proto_discriminator;
208 nas->header.message_type = nas_header_short.message_type;
209 }
210 } else {
211 log_msg(LOG_INFO, "No security header\n");
212 memcpy(&nas_header_short, msg, sizeof(nas_header_short)); /*copy only till msg type*/
213 msg += 2;
214
215 nas->header.security_header_type = nas_header_short.security_header_type;
216 nas->header.proto_discriminator = nas_header_short.proto_discriminator;
217 nas->header.message_type = nas_header_short.message_type;
218 }
219
220
221 log_msg(LOG_INFO, "Nas msg type: %X\n", nas->header.message_type);
222
223 switch(nas->header.message_type) {
224 case NAS_ESM_RESP:{
225 log_msg(LOG_INFO, "NAS_ESM_RESP recvd\n");
226
227 unsigned char element_id;
228 memcpy(&element_id, msg, 1);
229 msg++;
230 nas->elements_len +=1;
231
232 nas->elements = calloc(sizeof(nas_pdu_elements), 2);
233 //if(NULL == nas.elements)...
234
235 nas->elements[0].msgType = NAS_IE_TYPE_APN;
236 memcpy(&(nas->elements[0].pduElement.apn.len), msg, 1);
237 msg++;
238 memcpy(nas->elements[0].pduElement.apn.val, msg, nas->elements[0].pduElement.apn.len);
239 log_msg(LOG_INFO, "APN name - %s\n", nas->elements[0].pduElement.apn.val);
240 break;
241 }
242
243 case NAS_SEC_MODE_COMPLETE:
244 log_msg(LOG_INFO, "NAS_SEC_MODE_COMPLETE recvd\n");
245 break;
246
247 case NAS_AUTH_RESP:
248 log_msg(LOG_INFO, "NAS_AUTH_RESP recvd\n");
249 nas->elements_len = 1;
250 nas->elements = calloc(sizeof(nas_pdu_elements), 5);
251 //if(NULL == nas.elements)...
252 unsigned short len = get_length(&msg);
253 memcpy(&(nas->elements[0].pduElement.auth_resp), msg, sizeof(struct XRES));
254
255 break;
256
257 case NAS_IDENTITY_RESPONSE: {
258 log_msg(LOG_INFO, "NAS_IDENTITY_RESPONSE recvd\n");
259 nas->elements_len = 1;
260 nas->elements = calloc(sizeof(nas_pdu_elements), 1);
261 unsigned short imsi_len = get_length(&msg);
262 /*EPS mobility identity. TODO : More error checking */
263 memcpy(&(nas->elements[0].pduElement.IMSI), msg, imsi_len);
264 break;
265 }
266
267 case NAS_TAU_REQUEST:
268 log_msg(LOG_INFO, "NAS_TAU_REQUEST recvd\n");
269 break;
270
271 case NAS_AUTH_FAILURE:
272 {
273 nas->elements_len = 1;
274 nas->elements = calloc(sizeof(nas_pdu_elements), 1);
275 //if(NULL == nas.elements)...
276 char err = *(char*)(msg);
277 if(err == AUTH_SYNC_FAILURE)
278 {
279 log_msg(LOG_INFO, "AUTH Sync Failure. Start Re-Sync");
280 nas->elements[0].msgType = NAS_IE_TYPE_AUTH_FAIL_PARAM;
281 memcpy(&(nas->elements[0].pduElement.auth_fail_resp), msg + 2, sizeof(struct AUTS));
282 }
283 else
284 {
285 log_msg(LOG_ERROR, "Authentication Failure. Mac Failure");
286 }
287
288 }break;
289 case NAS_ATTACH_REQUEST:{
290 log_msg(LOG_INFO, "NAS_ATTACH_REQUEST recvd\n");
291
292 unsigned char tmp = msg[0];
293 nas->header.security_encryption_algo = (tmp & 0xF0) >> 4;
294 nas->header.security_integrity_algo = tmp & 0x0F;
295 msg++;
296
297 nas->elements_len = 7;
298 nas->elements = calloc(sizeof(nas_pdu_elements), nas->elements_len);
299
300
301 int index = 0;
302 unsigned short imsi_len = get_length(&msg);
303
304 bool odd = msg[0] & 0x08;
305 unsigned char eps_identity = msg[0] & 0x07;
306 switch(eps_identity) {
307 case 0x01: {
308 // Mobile Identity contains imsi
309 nas->flags |= NAS_MSG_UE_IE_IMSI;
310 log_msg(LOG_INFO, "IMSI len=%u - %u\n", imsi_len, BINARY_IMSI_LEN);
311 nas->elements[index].msgType = NAS_IE_TYPE_EPS_MOBILE_ID_IMSI;
312 memcpy(&(nas->elements[index].pduElement.IMSI), msg, imsi_len);
313 break;
314 }
315 case 0x06: {
316 log_msg(LOG_INFO, "Mobile identity GUTI Rcvd \n");
317 // Mobile Identity contains GUTI
318 // MCC+MNC offset = 3
319 // MME Group Id = 2
320 // MME Code = 1
321 // MTMSI offset from start of this AVP = 3 + 2 + 1
322 nas->elements[index].msgType = NAS_IE_TYPE_EPS_MOBILE_ID_IMSI;
323 memcpy(&nas->elements[index].pduElement.mi_guti.plmn_id.idx, &msg[1], 3);
324 nas->elements[index].pduElement.mi_guti.mme_grp_id = ntohs(*(short int *)(&msg[4]));
325 nas->elements[index].pduElement.mi_guti.mme_code = msg[6];
326 nas->elements[index].pduElement.mi_guti.m_TMSI = ntohl(*((unsigned int *)(&msg[7])));
327 log_msg(LOG_INFO, "NAS Attach Request Rcvd ID: GUTI. PLMN id %d %d %d \n", nas->elements[index].pduElement.mi_guti.plmn_id.idx[0],
328 nas->elements[index].pduElement.mi_guti.plmn_id.idx[1],
329 nas->elements[index].pduElement.mi_guti.plmn_id.idx[2] );
330 log_msg(LOG_INFO, "NAS Attach Request Rcvd ID: GUTI. mme group id = %d, MME code %d mtmsi = %d\n",
331 nas->elements[index].pduElement.mi_guti.mme_grp_id,
332 nas->elements[index].pduElement.mi_guti.mme_code,
333 nas->elements[index].pduElement.mi_guti.m_TMSI);
334 nas->flags |= NAS_MSG_UE_IE_GUTI;
335 break;
336 }
337 case 0x03: {
338 // Mobile Identity contains imei
339 break;
340 }
341 }
342
343 msg += imsi_len;
344 char *buffer = NULL;
345 log_msg(LOG_INFO, "IMSI=%s [to be read nibble-swapped]\n",
346 msg_to_hex_str((char *)nas->elements[index].pduElement.IMSI, imsi_len, &buffer));
347 log_buffer_free(&buffer);
348
349 /*UE network capacity*/
350 index++;
351 nas->elements[index].msgType =
352 NAS_IE_TYPE_UE_NETWORK_CAPABILITY;
353 nas->elements[index].pduElement.ue_network.len = msg[0];
354 msg++;
355 memcpy(
356 (nas->elements[index].pduElement.ue_network.capab)
357 ,msg,
358 nas->elements[index].pduElement.ue_network.len);
359 msg += nas->elements[index].pduElement.ue_network.len;
360
361 index++;
362 /*ESM msg container*/
363 len = msg[0] << 8 | msg[1];
364 msg += 2;
365 //now msg points to ESM message contents
366 log_msg(LOG_INFO, "len=%x\n", len);
367 log_msg(LOG_INFO, "msg[0]=%x\n", msg[0]);
368 nas->elements[index].pduElement.pti = msg[1];
369 nas->elements[index].msgType = NAS_IE_TYPE_PTI;
370 log_msg(LOG_INFO, "pti=%x\n", nas->elements[index].pduElement.pti);
371 unsigned short int msg_offset = 4;
372 /*ESM message header len is 4: bearer_id_flags(1)+proc_tx_id(1)+msg_id(1)
373 * +pdn_type(1)*/
374 /*element id 13(1101....) = "esm required" flag*/
375 //if tx_flag is absent then it means flag is set to false
376 //nas->elements[index].pduElement.esm_info_tx_required = false;
377 while(msg_offset < len)
378 {
379 unsigned char val = msg[msg_offset];
380 log_msg(LOG_INFO, "ESM container AVP val=%x\n", val);
381 if(13 == (val>>4))
382 {
383 index++;
384 nas->elements[index].msgType = NAS_IE_TYPE_TX_FLAG;
385 // byte 0 - EBI+PD, byte1 - pti, byte2 - message type, byte3 - pdntype+reqtype, byte4 - ESM info transfer flag == Total 5 bytes... msg[0] to msg[4]
386 //nas->elements[2].esm_info_tx_required = true;
387 if(val & 1) {
388 nas->elements[index].pduElement.esm_info_tx_required = true;
389 log_msg(LOG_INFO, "ESM information requested ");
390 }
391 msg_offset++; /* just one byte AVP */
392 continue;
393
394 }
395
396 if(0x27 == val)
397 {
398 unsigned short int pco_offset = msg_offset;
399 unsigned char pco_length = msg[msg_offset+1];
400 pco_offset += 2; // now points to first pco payload byte
401 pco_offset += 1; // 1 byte header skipping Extension + Configuration Protocol
402 unsigned short int pco_options=0;
403 log_msg(LOG_INFO, "PCO length %d Msg offset = %d , pco offset = %d ", pco_length, msg_offset, pco_offset);
404 index++;
405 nas->elements[index].msgType = NAS_IE_TYPE_PCO;
406 while(pco_offset < (msg_offset + pco_length))
407 {
408 log_msg(LOG_INFO, "Inside PCO length %d Msg offset = %d , pco offset = %d ", pco_length, msg_offset, pco_offset);
409 unsigned short int type;
410 unsigned char oct_len;
411 memcpy(&type, &msg[pco_offset], sizeof(type));
412 type = htons(type);
413 pco_offset += 2;
414 oct_len = msg[pco_offset];
415 pco_offset += 1;
416 log_msg(LOG_INFO, "pco element_id=%x len %d \n", type, oct_len);
417 if(type == 0x8021)
418 {
419 nas->elements[index].pduElement.pco_options[pco_options] = 0x8021;
420 pco_options++;
421 }
422 else if(type == 0x000d)
423 {
424 nas->elements[index].pduElement.pco_options[pco_options] = 0x000d;
425 pco_options++;
426 }
427 else if(type == 0x000a)
428 {
429 nas->elements[index].pduElement.pco_options[pco_options] = 0x000a;
430 pco_options++;
431 }
432 else if(type == 0x0005)
433 {
434 nas->elements[index].pduElement.pco_options[pco_options] = 0x0005;
435 pco_options++;
436 }
437 else if(type == 0x0010)
438 {
439 nas->elements[index].pduElement.pco_options[pco_options] = 0x0010;
440 pco_options++;
441 }
442 else if(type == 0x0011)
443 {
444 nas->elements[index].pduElement.pco_options[pco_options] = 0x0011;
445 pco_options++;
446 }
447 pco_offset += oct_len;
448 }
449
450 //pco
451 msg_offset = pco_length + 2; // msg offset was already at PCO AVP type. Now it should point to next AVP type
452 continue;
453 }
454 break; // unhandled ESM AVP...Add support..for now just break out..else we would be in tight loop
455 }
456 msg += len;
457
458 unsigned char elem_id = msg[0];
459 while(msg != msg_end)
460 {
461 elem_id = msg[0];
462 elem_id >>= 4;
463 if((NAS_IE_TYPE_GUTI_TYPE == elem_id)
464 || (NAS_IE_TYPE_TMSI_STATUS == elem_id)
465 || (NAS_IE_TYPE_MS_NETWORK_FEATURE_SUPPORT == elem_id))
466 {
467 switch(elem_id)
468 {
469 case NAS_IE_TYPE_GUTI_TYPE:
470 {
471 log_msg(LOG_DEBUG, "Old guti type : Skipping.\n");
472 msg++;
473 }break;
474 case NAS_IE_TYPE_TMSI_STATUS:
475 {
476 log_msg(LOG_DEBUG, "TMSI Status : Skipping.\n");
477 msg++;
478 }break;
479 case NAS_IE_TYPE_MS_NETWORK_FEATURE_SUPPORT:
480 {
481 log_msg(LOG_DEBUG, "MS Network feature support : Skipping.\n");
482 msg++;
483 }break;
484 default:
485 log_msg(LOG_WARNING, "Unknown AVP in attach msg. %d \n",elem_id);
486 msg++;
487 }
488
489 continue;
490 }
491 else
492 {
493 elem_id = msg[0];
494 switch(elem_id)
495 {
496 case NAS_IE_TYPE_DRX_PARAM:
497 {
498 log_msg(LOG_DEBUG, "DRX Param : Skipping.\n");
499 msg += 3;
500 }break;
501 case NAS_IE_TYPE_TAI:
502 {
503 log_msg(LOG_DEBUG, "TAI : Skipping.\n");
504 msg += 6;
505 }break;
506 case NAS_IE_TYPE_MS_CLASSMARK_2:
507 {
508 log_msg(LOG_DEBUG, "MS classmark 2 : Skipping.\n");
509 int len = msg[1];
510 msg += len + 2; //msgid + len field + len;
511 }break;
512 case NAS_IE_TYPE_VOICE_DOMAIN_PREF_UE_USAGE_SETTING:
513 {
514 log_msg(LOG_DEBUG, "Voice domain UE Usage : Skipping.\n");
515 int len = msg[1];
516 msg += len + 2; //msgid + len field + len;
517 }break;
518 case NAS_IE_TYPE_MS_NETWORK_CAPABILITY:
519 {
520 log_msg(LOG_DEBUG, "MS Network capability : Handling.\n");
521 index++;
522 nas->elements[index].msgType = NAS_IE_TYPE_MS_NETWORK_CAPABILITY;
523 nas->elements[index].pduElement.ms_network.pres = true;
524 nas->elements[index].pduElement.ms_network.element_id
525 = msg[0];
526 msg++;
527 nas->elements[index].pduElement.ms_network.len = msg[0];
528 msg++;
529 memcpy(
530 (nas->elements[index].pduElement.ms_network.capab),
531 msg,
532 nas->elements[index].pduElement.ms_network.len);
533 msg +=
534 nas->elements[index].pduElement.ms_network.len;
535 }break;
536 default:
537 log_msg(LOG_WARNING, "Unknown AVP in Attach Req %d \n", elem_id);
538 msg++;
539 }
540
541 continue;
542 }
543 }
544 break;
545 }
546
547 case NAS_ATTACH_COMPLETE:
548 log_msg(LOG_INFO, "NAS_ATTACH_COMPLETE recvd\n");
549 /*Other than error check there seems no information to pass to mme. Marking TODO for protocol study*/
550 break;
551
552 case NAS_DETACH_REQUEST: {
553 log_msg(LOG_INFO, "NAS_DETACH_REQUEST recvd\n");
554 nas->elements_len = 1;
555 nas->elements = calloc(sizeof(nas_pdu_elements), 1);
556
557 /*EPS mobility identity*/
558 memcpy(&(nas->elements[0].pduElement.mi_guti), msg + 11, sizeof(guti));
559 log_msg(LOG_INFO, "M-TMSI - %d\n", nas->elements[0].pduElement.mi_guti.m_TMSI);
560 break;
561 }
562
563 case NAS_DETACH_ACCEPT: {
564 log_msg(LOG_INFO, "NAS_DETACH_ACCEPT recvd\n");
565 break;
566 }
567
568 default:
569 log_msg(LOG_ERROR, "Unknown NAS Message type- 0x%x\n", nas->header.message_type);
570 break;
571
572 }
573}
574
575
576int
577parse_IEs(char *msg, struct proto_IE *proto_ies, unsigned short proc_code)
578{
579 unsigned short int no_of_IEs=0;
580
581 //short data_size=0;
582 //msg +=1;
583 //memcpy(&data_size, msg, 1);
584
585 //msg +=2;
586 memcpy(&no_of_IEs, msg, 2);
587 //no_of_IEs=msg[0];
588 no_of_IEs = ntohs(no_of_IEs);
589
590 /*Dumb logic....protocol or is creepy. Len sometimes comes in 3 bytes. How to know that??*/
591 if(0 == no_of_IEs) {
592 ++msg;
593 memcpy(&no_of_IEs, msg, 2);
594 no_of_IEs = ntohs(no_of_IEs);
595 }
596
597 log_msg(LOG_INFO, "No. of IEs = %d\n", no_of_IEs);
598 proto_ies->no_of_IEs = no_of_IEs;
599 proto_ies->data = calloc(sizeof(struct proto_IE_data), no_of_IEs);
600 //alloc fail chk
601 msg+=2;
602
603 for(int i=0; i < no_of_IEs; ++i) {
604 struct proto_IE_data *ie = &(proto_ies->data[i]);
605 unsigned short IE_type, IE_data_len = 0;
606
607 memcpy(&IE_type, msg, sizeof(short int));
608 IE_type = ntohs(IE_type);
609 ie->IE_type = IE_type;
610 msg +=2;//next to ie type
611 msg +=1;//next to criticality
612
613 IE_data_len = get_length(&msg);
614 log_msg(LOG_INFO, "IE [%d]: type = %d\n", i, IE_type);
615 log_msg(LOG_INFO, "IE [%d]: data len= %x - %u\n", i, IE_data_len, IE_data_len);
616
617 char *buffer = NULL;
618 log_msg(LOG_INFO, "IE [%d]: value= %s\n", i, msg_to_hex_str(msg, IE_data_len, &buffer));
619 log_buffer_free(&buffer);
620
621 /*Based on IE_Type call the parser to read IE info*/
622 /*TODO: optimize with function ptr etc.*/
623 switch(IE_type) {
624 case S1AP_IE_GLOBAL_ENB_ID:
625 log_msg(LOG_INFO, "IE [%d]: parse global eNB ID\n", i);
626 ie_parse_global_enb_id(msg+6, IE_data_len);
627 break;
628
629 case S1AP_IE_ENB_NAME:
630 log_msg(LOG_INFO, "IE [%d]: parse global eNB name\n", i);
631 ie_parse_enb_name(msg, IE_data_len);
632 break;
633
634 case S1AP_IE_SUPPORTED_TAS:
635 break;
636
637 case S1AP_IE_DEF_PAGING_DRX:
638 break;
639
640 case S1AP_IE_MME_UE_ID:{
641 ie->val.mme_ue_s1ap_id = decode_int_val((unsigned char *)msg,
642 IE_data_len);
643 log_msg(LOG_INFO, "IE [%d]: parse MME_UE_S1AP_ID - %d\n", i,
644 ie->val.mme_ue_s1ap_id);
645 break;
646 }
647
648 case S1AP_IE_ENB_UE_ID:{
649 ie->val.enb_ue_s1ap_id = decode_int_val((unsigned char *)msg,
650 IE_data_len);
651 log_msg(LOG_INFO, "IE [%d]: parse ENB_UE_S1AP_ID - %d\n", i,
652 ie->val.enb_ue_s1ap_id);
653 break;
654 }
655
656 case S1AP_IE_TAI:{
657 log_msg(LOG_INFO, "IE [%d]: TAI parse\n", i);
658 memcpy(&(ie->val.tai), msg+1, sizeof(struct TAI));
659 log_msg(LOG_INFO, "IE [%d]: plmn-%x %x %x, tac-%d\n", i,
660 ie->val.tai.plmn_id.idx[0],
661 ie->val.tai.plmn_id.idx[1], ie->val.tai.plmn_id.idx[2],
662 ie->val.tai.tac);
663 break;
664 }
665
666 case S1AP_IE_UTRAN_CGI:{
667 log_msg(LOG_INFO, "IE [%d]: EUTRAN CGI\n", i);
668 memset(&(ie->val.utran_cgi), 0, sizeof(struct CGI));
669 memcpy(&(ie->val.utran_cgi), msg+1, sizeof(struct CGI));
670 log_msg(LOG_INFO, "IE [%d]: plmn-%x %x %x, cell-%d\n", i,
671 ie->val.utran_cgi.plmn_id.idx[0],
672 ie->val.utran_cgi.plmn_id.idx[1], ie->val.utran_cgi.plmn_id.idx[2],
673 ie->val.utran_cgi.cell_id);
674 break;
675 }
676
677 case S1AP_IE_NAS_PDU: {
678 log_msg(LOG_INFO, "IE [%d]: NAS msg type parsed = %x\n", i,
679 ie->val.nas.header.message_type);
680 parse_nas_pdu(msg, IE_data_len, &ie->val.nas, proc_code);
681 break;
682 }
683
684 case S1AP_IE_RRC_EST_CAUSE: {
685 log_msg(LOG_INFO, "IE [%d]: parse RRC establishment code - %d\n", i,
686 ie->val.rrc_est_cause);
687 break;
688 }
689
690 case S1AP_ERAB_SETUP_CTX_SUR:
691 log_msg(LOG_INFO, "IE [%d]: parse S1AP_ERAB_SETUP_CTX_SUR parse_erab_pdu \n", i);
692 parse_erab_pdu(msg, IE_data_len, &ie->val.erab);
693 break;
694
695 default:
696 log_msg(LOG_INFO, "IE [%d]: Check IE type %d\n", i, IE_type);
697 break;
698 }
699
700 msg += (IE_data_len);
701 if(128 == IE_data_len) ++msg;//TODO: byte size issue. chk thi.
702 }
703 return 0;
704}
705
706int convertToInitUeProtoIe(InitiatingMessage_t *msg, struct proto_IE* proto_ies)
707{
708 proto_ies->procedureCode = msg->procedureCode;
709 proto_ies->criticality = msg->criticality;
710
711 if(msg->value.present == InitiatingMessage__value_PR_InitialUEMessage)
712 {
713 ProtocolIE_Container_129P32_t* protocolIes = &msg->value.choice.InitialUEMessage.protocolIEs;
714 proto_ies->no_of_IEs = protocolIes->list.count;
715
716 log_msg(LOG_INFO, "No of IEs = %d\n", proto_ies->no_of_IEs);
717 proto_ies->data = calloc(sizeof(struct proto_IE_data), proto_ies->no_of_IEs);
718 if(proto_ies->data == NULL) {
719 log_msg(LOG_ERROR,"Calloc failed for protocol IE.");
720 return -1;
721 }
722 for (int i = 0; i < protocolIes->list.count; i++) {
723 InitialUEMessage_IEs_t *ie_p;
724 ie_p = protocolIes->list.array[i];
725 switch(ie_p->id) {
726 case ProtocolIE_ID_id_eNB_UE_S1AP_ID:
727 {
728 ENB_UE_S1AP_ID_t *s1apENBUES1APID_p = NULL;
729 if(InitialUEMessage_IEs__value_PR_ENB_UE_S1AP_ID == ie_p->value.present)
730 {
731 s1apENBUES1APID_p = &ie_p->value.choice.ENB_UE_S1AP_ID;
732 }
733
734 if (s1apENBUES1APID_p == NULL) {
735 log_msg (LOG_ERROR, "Decoding of IE eNB_UE_S1AP_ID failed\n");
736 return -1;
737 }
738
739 log_msg(LOG_DEBUG, "ENB UE S1ap ID decode Success\n");
740 proto_ies->data[i].IE_type = S1AP_IE_ENB_UE_ID;
741 memcpy(&proto_ies->data[i].val.enb_ue_s1ap_id, s1apENBUES1APID_p, sizeof(ENB_UE_S1AP_ID_t));
742 s1apENBUES1APID_p = NULL;
743 } break;
744 case ProtocolIE_ID_id_NAS_PDU:
745 {
746 NAS_PDU_t *s1apNASPDU_p = NULL;
747 if(InitialUEMessage_IEs__value_PR_NAS_PDU == ie_p->value.present)
748 {
749 s1apNASPDU_p = &ie_p->value.choice.NAS_PDU;
750 }
751
752 if (s1apNASPDU_p == NULL) {
753 log_msg (LOG_ERROR, "Decoding of IE NAS PDU failed\n");
754 return -1;
755 }
756
757 log_msg(LOG_DEBUG, "NAS PDU decode Success\n");
758 proto_ies->data[i].IE_type = S1AP_IE_NAS_PDU;
759 parse_nas_pdu((char*)s1apNASPDU_p->buf, s1apNASPDU_p->size,
760 &proto_ies->data[i].val.nas, msg->procedureCode);
761 s1apNASPDU_p = NULL;
762 } break;
763 case ProtocolIE_ID_id_TAI:
764 {
765 TAI_t *s1apTAI_p = NULL;
766 if(InitialUEMessage_IEs__value_PR_TAI == ie_p->value.present)
767 {
768 s1apTAI_p = &ie_p->value.choice.TAI;
769 }
770
771 if (s1apTAI_p == NULL) {
772 log_msg (LOG_ERROR, "Decoding of IE TAI failed\n");
773 return -1;
774 }
775
776 log_msg(LOG_DEBUG, "TAI decode Success\n");
777 proto_ies->data[i].IE_type = S1AP_IE_TAI;
778 memcpy(&proto_ies->data[i].val.tai.tac, s1apTAI_p->tAC.buf, s1apTAI_p->tAC.size);
779 memcpy(proto_ies->data[i].val.tai.plmn_id.idx,
780 s1apTAI_p->pLMNidentity.buf, s1apTAI_p->pLMNidentity.size);
781 s1apTAI_p = NULL;
782 } break;
783 case ProtocolIE_ID_id_EUTRAN_CGI:
784 {
785 EUTRAN_CGI_t* s1apCGI_p = NULL;;
786 if(InitialUEMessage_IEs__value_PR_EUTRAN_CGI == ie_p->value.present)
787 {
788 s1apCGI_p = &ie_p->value.choice.EUTRAN_CGI;
789 }
790
791 if (s1apCGI_p == NULL) {
792 log_msg (LOG_ERROR, "Decoding of IE CGI failed\n");
793 return -1;
794 }
795
796 log_msg(LOG_DEBUG, "CGI decode Success\n");
797 proto_ies->data[i].IE_type = S1AP_IE_UTRAN_CGI;
798 memcpy(&proto_ies->data[i].val.utran_cgi.cell_id,
799 s1apCGI_p->cell_ID.buf, s1apCGI_p->cell_ID.size);
800 memcpy(proto_ies->data[i].val.utran_cgi.plmn_id.idx,
801 s1apCGI_p->pLMNidentity.buf, s1apCGI_p->pLMNidentity.size);
802 s1apCGI_p = NULL;
803 } break;
804 case ProtocolIE_ID_id_RRC_Establishment_Cause:
805 {
806 RRC_Establishment_Cause_t *s1apRRCEstCause_p;
807 if(InitialUEMessage_IEs__value_PR_RRC_Establishment_Cause == ie_p->value.present)
808 {
809 s1apRRCEstCause_p = &ie_p->value.choice.RRC_Establishment_Cause;
810 }
811
812 if (s1apRRCEstCause_p == NULL) {
813 log_msg (LOG_ERROR, "Decoding of IE RRC Cause failed\n");
814 return -1;
815 }
816
817 log_msg(LOG_DEBUG, "RRC Cause decode Success\n");
818 proto_ies->data[i].IE_type = S1AP_IE_RRC_EST_CAUSE;
819 proto_ies->data[i].val.rrc_est_cause = (enum ie_RRC_est_cause) *s1apRRCEstCause_p;
820 s1apRRCEstCause_p = NULL;
821 } break;
822 case ProtocolIE_ID_id_S_TMSI:
823 {
824 S_TMSI_t* s1apStmsi_p = NULL;;
825 if(InitialUEMessage_IEs__value_PR_S_TMSI == ie_p->value.present)
826 {
827 s1apStmsi_p = &ie_p->value.choice.S_TMSI;
828 }
829
830 if (s1apStmsi_p == NULL) {
831 log_msg (LOG_ERROR, "Decoding of IE STMSI failed\n");
832 return -1;
833 }
834
835 //struct STMSI s_tmsi
836 proto_ies->data[i].IE_type = S1AP_IE_S_TMSI;
837 memcpy(&proto_ies->data[i].val.s_tmsi.mme_code,
838 s1apStmsi_p->mMEC.buf, sizeof(uint8_t));
839 memcpy(&proto_ies->data[i].val.s_tmsi.m_TMSI,
840 s1apStmsi_p->m_TMSI.buf, sizeof(uint32_t));
841 s1apStmsi_p = NULL;
842 } break;
843 default:
844 {
845 log_msg(LOG_WARNING, "Unhandled IE %d in initial UE message ", ie_p->id);
846 }
847 }
848 }
849 }
850
851 return 0;
852}
853
854static int
855init_ue_msg_handler(InitiatingMessage_t *msg, int enb_fd)
856{
857 //TODO: use static instead of synamic for perf.
858 struct proto_IE proto_ies;
859
860 log_msg(LOG_INFO, "S1AP_INITIAL_UE_MSG msg: \n");
861
862 /* TODO : Error handling. Bad message will lead crash.
863 * Preferably reject the message, increment stats.
864 */
865 int decode_result = convertToInitUeProtoIe(msg, &proto_ies);
866 if(decode_result < 0 )
867 {
868 log_msg(LOG_ERROR, "S1ap message decode failed. Dropping message");
869 return E_FAIL;
870 }
871
872 /*Check nas message type*/
873 //TODO: check through all proto IEs for which is nas
874 //currentlyy hard coding to 2 looking at packets
875 log_msg(LOG_INFO, "NAS msg type parsed = %x\n", proto_ies.data[1].val.nas.header.message_type);
876 switch(proto_ies.data[1].val.nas.header.message_type) {
877 case NAS_ATTACH_REQUEST:
878 s1_init_ue_handler(&proto_ies, enb_fd);
879 break;
880
881 case NAS_SERVICE_REQUEST:
882 s1_init_ue_service_req_handler(&proto_ies, enb_fd);
883 break;
884
885 case NAS_DETACH_REQUEST:
886 detach_stage1_handler(&proto_ies, true);
887 break;
888
889 case NAS_DETACH_ACCEPT:
890 detach_accept_from_ue_handler(&proto_ies, true);
891 break;
892
893 case NAS_TAU_REQUEST:
894 tau_request_handler(&proto_ies, enb_fd);
895 break;
896 }
897
898 free(proto_ies.data);
899 //TODO: free IEs
900 return SUCCESS;
901}
902
903static int
904UL_NAS_msg_handler(InitiatingMessage_t *msg, int enb_fd)
905{
906 //TODO: use static instead of synamic for perf.
907 struct proto_IE proto_ies;
908
909 log_msg(LOG_INFO, "S1AP_UL_NAS_TX_MSG msg \n");
910
911 convertUplinkNasToProtoIe(msg, &proto_ies);
912
913 /*Check nas message type*/
914 //TODO: check through all proto IEs for which is nas
915 //currentlyy hard coding to 2 looking at packets
916 log_msg(LOG_INFO, "NAS msg type = %x\n", proto_ies.data[2].val.nas.header.message_type);
917 switch(proto_ies.data[2].val.nas.header.message_type) {
918 case NAS_AUTH_RESP:
919 s1_auth_resp_handler(&proto_ies);
920 break;
921
922 case NAS_AUTH_FAILURE:
923 s1_auth_fail_handler(&proto_ies);
924 break;
925
926 case NAS_ATTACH_REQUEST:
927 s1_init_ue_handler(&proto_ies, enb_fd);
928 break;
929
930 case NAS_SEC_MODE_COMPLETE:
931 s1_secmode_resp_handler(&proto_ies);
932 break;
933
934 case NAS_ESM_RESP:
935 s1_esm_resp_handler(&proto_ies);
936 break;
937
938 case NAS_ATTACH_COMPLETE:
939 s1_attach_complete_handler(&proto_ies);
940 break;
941
942 case NAS_DETACH_REQUEST:
943 detach_stage1_handler(&proto_ies, false);
944 break;
945
946 case NAS_DETACH_ACCEPT:
947 detach_accept_from_ue_handler(&proto_ies, false);
948 break;
949
950 case NAS_IDENTITY_RESPONSE:
951 s1_identity_resp_handler(&proto_ies);
952 break;
953
954 case NAS_TAU_REQUEST:
955 tau_request_handler(&proto_ies, enb_fd);
956 break;
957 }
958
959 //TODO: free IEs
960 free(proto_ies.data);
961 return SUCCESS;
962}
963
964void
965handle_s1ap_message(void *msg)
966{
967 log_msg(LOG_INFO, "Inside handle_s1ap_message.\n");
968 /*convert message from network to host*/
969
970 /*Call handler for the procedure code. TBD: Tasks pool for handlers*/
971
972 int enb_fd = 0;
973 int msg_size = 0;
974 memcpy(&enb_fd, msg, sizeof(int));
975 memcpy(&msg_size, msg + sizeof(int), sizeof(int));
976 char *message = ((char *) msg) + 2*sizeof(int);
977 S1AP_PDU_t pdu = {(S1AP_PDU_PR_NOTHING)};
978 S1AP_PDU_t *pdu_p = &pdu;
979 asn_dec_rval_t dec_ret = {(RC_OK)};
980 memset ((void *)pdu_p, 0, sizeof (S1AP_PDU_t));
981 dec_ret = aper_decode (NULL, &asn_DEF_S1AP_PDU, (void **)&pdu_p, message, msg_size, 0, 0);
982
983 if (dec_ret.code != RC_OK) {
984 log_msg(LOG_ERROR, "ASN Decode PDU Failed %d\n", dec_ret.consumed);
985 ASN__DECODE_FAILED;
986 free(msg);
987 return;
988 }
989
990 switch (pdu_p->present) {
991 case S1AP_PDU_PR_initiatingMessage:
992 s1ap_mme_decode_initiating (pdu_p->choice.initiatingMessage, enb_fd);
993 break;
994 case S1AP_PDU_PR_successfulOutcome:
995 s1ap_mme_decode_successfull_outcome (pdu_p->choice.successfulOutcome);
996 break;
997 case S1AP_PDU_PR_unsuccessfulOutcome:
998 s1ap_mme_decode_unsuccessfull_outcome (pdu_p->choice.unsuccessfulOutcome);
999 break;
1000 default:
1001 log_msg(LOG_WARNING, "Unknown message outcome (%d) or not implemented", (int)pdu_p->present);
1002 break;
1003 }
1004
1005 return;
1006}
1007
1008int
1009s1ap_mme_decode_successfull_outcome (SuccessfulOutcome_t* msg)
1010{
1011 log_msg(LOG_DEBUG,"successful outcome decode :");
1012 log_msg(LOG_INFO, "proc code %d\n", msg->procedureCode);
1013 switch (msg->procedureCode) {
1014
1015 case S1AP_INITIAL_CTX_RESP_CODE:
1016 s1_init_ctx_resp_handler(msg);
1017 break;
1018
1019 case S1AP_UE_CONTEXT_RELEASE_CODE:
1020 s1_ctx_release_complete_handler(msg);
1021 break;
1022
1023 default:
1024 log_msg(LOG_ERROR, "Unknown procedure code - %d\n",
1025 msg->procedureCode & 0x00FF);
1026 break;
1027 }
1028
1029 return 0;
1030}
1031
1032int
1033s1ap_mme_decode_unsuccessfull_outcome (UnsuccessfulOutcome_t *msg)
1034{
1035 log_msg(LOG_DEBUG,"unsuccessful outcome decode : TBD");
1036 return 0;
1037}
1038
1039int
1040s1ap_mme_decode_initiating (InitiatingMessage_t *initiating_p, int enb_fd)
1041{
1042 log_msg(LOG_INFO, "proc code %d\n", initiating_p->procedureCode);
1043 switch (initiating_p->procedureCode) {
1044
1045 case S1AP_SETUP_REQUEST_CODE:
1046 s1_setup_handler(initiating_p, enb_fd);
1047 break;
1048
1049 case S1AP_INITIAL_UE_MSG_CODE:
1050 init_ue_msg_handler(initiating_p, enb_fd);
1051 break;
1052
1053 case S1AP_UL_NAS_TX_MSG_CODE:
1054 UL_NAS_msg_handler(initiating_p, enb_fd);
1055 break;
1056
1057
1058 case S1AP_UE_CONTEXT_RELEASE_REQUEST_CODE:
1059 s1_ctx_release_request_handler(initiating_p);
1060 break;
1061
1062 default:
1063 log_msg(LOG_ERROR, "Unknown procedure code - %d\n",
1064 initiating_p->procedureCode & 0x00FF);
1065 break;
1066 }
1067
1068 //free(msg);
1069 return 0;
1070}
1071
1072int convertUplinkNasToProtoIe(InitiatingMessage_t *msg, struct proto_IE* proto_ies)
1073{
1074 proto_ies->procedureCode = msg->procedureCode;
1075 proto_ies->criticality = msg->criticality;
1076 int no_of_IEs = 0;
1077
1078 if(msg->value.present == InitiatingMessage__value_PR_UplinkNASTransport)
1079 {
1080 ProtocolIE_Container_129P33_t* protocolIes = &msg->value.choice.UplinkNASTransport.protocolIEs;
1081 no_of_IEs = protocolIes->list.count;
1082 proto_ies->no_of_IEs = no_of_IEs;
1083
1084 log_msg(LOG_INFO, "No of IEs = %d\n", no_of_IEs);
1085 proto_ies->data = calloc(sizeof(struct proto_IE_data), no_of_IEs);
1086 if(proto_ies->data == NULL)
1087 {
1088 log_msg(LOG_ERROR,"Malloc failed for protocol IE.");
1089 return -1;
1090 }
1091 for (int i = 0; i < protocolIes->list.count; i++) {
1092 UplinkNASTransport_IEs_t *ie_p;
1093 ie_p = protocolIes->list.array[i];
1094 switch(ie_p->id) {
1095 case ProtocolIE_ID_id_eNB_UE_S1AP_ID:
1096 {
1097 ENB_UE_S1AP_ID_t *s1apENBUES1APID_p = NULL;
1098 if(UplinkNASTransport_IEs__value_PR_ENB_UE_S1AP_ID == ie_p->value.present)
1099 {
1100 s1apENBUES1APID_p = &ie_p->value.choice.ENB_UE_S1AP_ID;
1101 }
1102
1103 if (s1apENBUES1APID_p == NULL) {
1104 log_msg (LOG_ERROR, "Decoding of IE eNB_UE_S1AP_ID failed\n");
1105 return -1;
1106 }
1107
1108 proto_ies->data[i].IE_type = S1AP_IE_ENB_UE_ID;
1109 memcpy(&proto_ies->data[i].val.enb_ue_s1ap_id, s1apENBUES1APID_p, sizeof(ENB_UE_S1AP_ID_t));
1110 s1apENBUES1APID_p = NULL;
1111 } break;
1112 case ProtocolIE_ID_id_MME_UE_S1AP_ID:
1113 {
1114 MME_UE_S1AP_ID_t *s1apMMEUES1APID_p = NULL;
1115 if(UplinkNASTransport_IEs__value_PR_MME_UE_S1AP_ID == ie_p->value.present)
1116 {
1117 s1apMMEUES1APID_p = &ie_p->value.choice.MME_UE_S1AP_ID;
1118 }
1119
1120 if (s1apMMEUES1APID_p == NULL) {
1121 log_msg (LOG_ERROR, "Decoding of IE MME_UE_S1AP_ID failed\n");
1122 return -1;
1123 }
1124
1125 proto_ies->data[i].IE_type = S1AP_IE_MME_UE_ID;
1126 memcpy(&proto_ies->data[i].val.mme_ue_s1ap_id, s1apMMEUES1APID_p, sizeof(MME_UE_S1AP_ID_t));
1127 s1apMMEUES1APID_p = NULL;
1128 } break;
1129 case ProtocolIE_ID_id_NAS_PDU:
1130 {
1131 NAS_PDU_t *s1apNASPDU_p = NULL;
1132 if(UplinkNASTransport_IEs__value_PR_NAS_PDU == ie_p->value.present)
1133 {
1134 s1apNASPDU_p = &ie_p->value.choice.NAS_PDU;
1135 }
1136
1137 if (s1apNASPDU_p == NULL) {
1138 log_msg (LOG_ERROR, "Decoding of IE NAS PDU failed\n");
1139 return -1;
1140 }
1141
1142 proto_ies->data[i].IE_type = S1AP_IE_NAS_PDU;
1143 parse_nas_pdu((char*)s1apNASPDU_p->buf, s1apNASPDU_p->size,
1144 &proto_ies->data[i].val.nas, msg->procedureCode);
1145 s1apNASPDU_p = NULL;
1146 } break;
1147 case ProtocolIE_ID_id_TAI:
1148 {
1149 TAI_t *s1apTAI_p = NULL;
1150 if(UplinkNASTransport_IEs__value_PR_TAI == ie_p->value.present)
1151 {
1152 s1apTAI_p = &ie_p->value.choice.TAI;
1153 }
1154
1155 if (s1apTAI_p == NULL) {
1156 log_msg (LOG_ERROR, "Decoding of IE TAI failed\n");
1157 return -1;
1158 }
1159
1160 proto_ies->data[i].IE_type = S1AP_IE_TAI;
1161 memcpy(&proto_ies->data[i].val.tai.tac, s1apTAI_p->tAC.buf, s1apTAI_p->tAC.size);
1162 memcpy(&proto_ies->data[i].val.tai.plmn_id,
1163 s1apTAI_p->pLMNidentity.buf, s1apTAI_p->pLMNidentity.size);
1164 s1apTAI_p = NULL;
1165 } break;
1166 case ProtocolIE_ID_id_EUTRAN_CGI:
1167 {
1168 EUTRAN_CGI_t* s1apCGI_p = NULL;;
1169 if(UplinkNASTransport_IEs__value_PR_EUTRAN_CGI == ie_p->value.present)
1170 {
1171 s1apCGI_p = &ie_p->value.choice.EUTRAN_CGI;
1172 }
1173
1174 if (s1apCGI_p == NULL) {
1175 log_msg (LOG_ERROR, "Decoding of IE CGI failed\n");
1176 return -1;
1177 }
1178
1179 proto_ies->data[i].IE_type = S1AP_IE_UTRAN_CGI;
1180 memcpy(&proto_ies->data[i].val.utran_cgi.cell_id,
1181 s1apCGI_p->cell_ID.buf, s1apCGI_p->cell_ID.size);
1182 memcpy(&proto_ies->data[i].val.utran_cgi.plmn_id.idx,
1183 s1apCGI_p->pLMNidentity.buf, s1apCGI_p->pLMNidentity.size);
1184 s1apCGI_p = NULL;
1185 } break;
1186 default:
1187 {
1188 log_msg(LOG_WARNING, "Unhandled IE %d", ie_p->id);
1189 }
1190 }
1191 }
1192 }
1193
1194 return 0;
1195}
1196
1197int convertInitCtxRspToProtoIe(SuccessfulOutcome_t *msg, struct proto_IE* proto_ies)
1198{
1199 proto_ies->procedureCode = msg->procedureCode;
1200 proto_ies->criticality = msg->criticality;
1201 int no_of_IEs = 0;
1202
1203 if(msg->value.present == SuccessfulOutcome__value_PR_InitialContextSetupResponse)
1204 {
1205 ProtocolIE_Container_129P20_t* protocolIes
1206 = &msg->value.choice.InitialContextSetupResponse.protocolIEs;
1207 no_of_IEs = protocolIes->list.count;
1208 proto_ies->no_of_IEs = no_of_IEs;
1209
1210 log_msg(LOG_INFO, "No of IEs = %d\n", no_of_IEs);
1211 proto_ies->data = calloc(sizeof(struct proto_IE_data), no_of_IEs);
1212 if(proto_ies->data == NULL)
1213 {
1214 log_msg(LOG_ERROR,"Malloc failed for protocol IE.");
1215 return -1;
1216 }
1217 for (int i = 0; i < protocolIes->list.count; i++) {
1218 InitialContextSetupResponseIEs_t *ie_p;
1219 ie_p = protocolIes->list.array[i];
1220 switch(ie_p->id) {
1221 case ProtocolIE_ID_id_eNB_UE_S1AP_ID:
1222 {
1223 ENB_UE_S1AP_ID_t *s1apENBUES1APID_p = NULL;
1224 if(InitialContextSetupResponseIEs__value_PR_ENB_UE_S1AP_ID == ie_p->value.present)
1225 {
1226 s1apENBUES1APID_p = &ie_p->value.choice.ENB_UE_S1AP_ID;
1227 }
1228
1229 if (s1apENBUES1APID_p == NULL) {
1230 log_msg (LOG_ERROR, "Decoding of IE eNB_UE_S1AP_ID failed\n");
1231 return -1;
1232 }
1233
1234 proto_ies->data[i].IE_type = S1AP_IE_ENB_UE_ID;
1235 memcpy(&proto_ies->data[i].val.enb_ue_s1ap_id, s1apENBUES1APID_p, sizeof(ENB_UE_S1AP_ID_t));
1236 s1apENBUES1APID_p = NULL;
1237 } break;
1238 case ProtocolIE_ID_id_MME_UE_S1AP_ID:
1239 {
1240 MME_UE_S1AP_ID_t *s1apMMEUES1APID_p = NULL;
1241 if(InitialContextSetupResponseIEs__value_PR_MME_UE_S1AP_ID == ie_p->value.present)
1242 {
1243 s1apMMEUES1APID_p = &ie_p->value.choice.MME_UE_S1AP_ID;
1244 }
1245
1246 if (s1apMMEUES1APID_p == NULL) {
1247 log_msg (LOG_ERROR, "Decoding of IE MME_UE_S1AP_ID failed\n");
1248 return -1;
1249 }
1250
1251 proto_ies->data[i].IE_type = S1AP_IE_MME_UE_ID;
1252 memcpy(&proto_ies->data[i].val.mme_ue_s1ap_id, s1apMMEUES1APID_p, sizeof(MME_UE_S1AP_ID_t));
1253 s1apMMEUES1APID_p = NULL;
1254 } break;
1255 case ProtocolIE_ID_id_E_RABSetupListCtxtSURes:
1256 {
1257 E_RABSetupListCtxtSURes_t *s1apErabSetupList_p = NULL;
1258 if(InitialContextSetupResponseIEs__value_PR_E_RABSetupListCtxtSURes == ie_p->value.present)
1259 {
1260 s1apErabSetupList_p = &ie_p->value.choice.E_RABSetupListCtxtSURes;
1261 }
1262
1263 if (s1apErabSetupList_p == NULL) {
1264 log_msg (LOG_ERROR, "Decoding of IE s1apErabSetupList failed\n");
1265 return -1;
1266 }
1267
1268 proto_ies->data[i].IE_type = S1AP_ERAB_SETUP_CTX_SUR;
1269 proto_ies->data[i].val.erab.no_of_elements = s1apErabSetupList_p->list.count;
1270 proto_ies->data[i].val.erab.elements = calloc(sizeof(union eRAB_IE),
1271 s1apErabSetupList_p->list.count);
1272 if(proto_ies->data[i].val.erab.elements == NULL)
1273 {
1274 log_msg(LOG_ERROR,"Malloc failed for protocol IE: Erab elements.");
1275 break;;
1276 }
1277 for (int j = 0;
1278 j < s1apErabSetupList_p->list.count; j++)
1279 {
1280 E_RABSetupItemCtxtSUResIEs_t *ie_p;
1281 ie_p = (E_RABSetupItemCtxtSUResIEs_t*)s1apErabSetupList_p->list.array[j];
1282 switch(ie_p->id) {
1283 case ProtocolIE_ID_id_E_RABSetupItemCtxtSURes:
1284 {
1285 E_RABSetupItemCtxtSURes_t* s1apErabSetupItem_p = NULL;
1286 if(E_RABSetupItemCtxtSUResIEs__value_PR_E_RABSetupItemCtxtSURes == ie_p->value.present)
1287 {
1288 s1apErabSetupItem_p = &ie_p->value.choice.E_RABSetupItemCtxtSURes;
1289 }
1290
1291 if (s1apErabSetupItem_p == NULL) {
1292 log_msg (LOG_ERROR, "Decoding of IE s1apErabSetupItem failed\n");
1293 return -1;
1294 }
1295
1296 proto_ies->data[i].val.erab.elements[j].su_res.eRAB_id
1297 = (unsigned short)s1apErabSetupItem_p->e_RAB_ID;
1298 memcpy(
1299 &(proto_ies->data[i].val.erab.elements[j].su_res.gtp_teid),
1300 s1apErabSetupItem_p->gTP_TEID.buf,
1301 s1apErabSetupItem_p->gTP_TEID.size);
1302 proto_ies->data[i].val.erab.elements[j].su_res.gtp_teid
1303 = ntohl(proto_ies->data[i].val.erab.elements[j].su_res.gtp_teid);
1304
1305 memcpy(
1306 &(proto_ies->data[i].val.erab.elements[j].su_res.transp_layer_addr),
1307 s1apErabSetupItem_p->transportLayerAddress.buf,
1308 s1apErabSetupItem_p->transportLayerAddress.size);
1309 proto_ies->data[i].val.erab.elements[j].su_res.transp_layer_addr
1310 = ntohl(proto_ies->data[i].val.erab.elements[j].su_res.transp_layer_addr);
1311 s1apErabSetupItem_p = NULL;
1312 }break;
1313 default:
1314 {
1315 log_msg(LOG_WARNING, "Unhandled List item %d", ie_p->id);
1316 }
1317 }
1318 }
1319
1320 s1apErabSetupList_p = NULL;
1321 } break;
1322 default:
1323 {
1324 log_msg(LOG_WARNING, "Unhandled IE %d", ie_p->id);
1325 }
1326 }
1327 }
1328 }
1329
1330 return 0;
1331}
1332
1333int convertUeCtxRelComplToProtoIe(SuccessfulOutcome_t *msg, struct proto_IE* proto_ies)
1334{
1335 proto_ies->procedureCode = msg->procedureCode;
1336 proto_ies->criticality = msg->criticality;
1337 int no_of_IEs = 0;
1338
1339 if(msg->value.present == SuccessfulOutcome__value_PR_UEContextReleaseComplete)
1340 {
1341 ProtocolIE_Container_129P25_t* protocolIes
1342 = &msg->value.choice.UEContextReleaseComplete.protocolIEs;
1343 no_of_IEs = protocolIes->list.count;
1344 proto_ies->no_of_IEs = no_of_IEs;
1345
1346 log_msg(LOG_INFO, "No of IEs = %d\n", no_of_IEs);
1347 proto_ies->data = calloc(sizeof(struct proto_IE_data), no_of_IEs);
1348 if(proto_ies->data == NULL)
1349 {
1350 log_msg(LOG_ERROR,"Malloc failed for protocol IE.");
1351 return -1;
1352 }
1353 for (int i = 0; i < protocolIes->list.count; i++) {
1354 UEContextReleaseComplete_IEs_t *ie_p;
1355 ie_p = protocolIes->list.array[i];
1356 switch(ie_p->id) {
1357 case ProtocolIE_ID_id_eNB_UE_S1AP_ID:
1358 {
1359 ENB_UE_S1AP_ID_t *s1apENBUES1APID_p = NULL;
1360 if(UEContextReleaseComplete_IEs__value_PR_ENB_UE_S1AP_ID == ie_p->value.present)
1361 {
1362 s1apENBUES1APID_p = &ie_p->value.choice.ENB_UE_S1AP_ID;
1363 }
1364
1365 if (s1apENBUES1APID_p == NULL) {
1366 log_msg (LOG_ERROR, "Decoding of IE eNB_UE_S1AP_ID failed\n");
1367 return -1;
1368 }
1369
1370 proto_ies->data[i].IE_type = S1AP_IE_ENB_UE_ID;
1371 memcpy(&proto_ies->data[i].val.enb_ue_s1ap_id, s1apENBUES1APID_p, sizeof(ENB_UE_S1AP_ID_t));
1372 s1apENBUES1APID_p = NULL;
1373 } break;
1374 case ProtocolIE_ID_id_MME_UE_S1AP_ID:
1375 {
1376 MME_UE_S1AP_ID_t *s1apMMEUES1APID_p = NULL;
1377 if(UEContextReleaseComplete_IEs__value_PR_MME_UE_S1AP_ID == ie_p->value.present)
1378 {
1379 s1apMMEUES1APID_p = &ie_p->value.choice.MME_UE_S1AP_ID;
1380 }
1381
1382 if (s1apMMEUES1APID_p == NULL) {
1383 log_msg (LOG_ERROR, "Decoding of IE MME_UE_S1AP_ID failed\n");
1384 return -1;
1385 }
1386
1387 proto_ies->data[i].IE_type = S1AP_IE_MME_UE_ID;
1388 memcpy(&proto_ies->data[i].val.mme_ue_s1ap_id, s1apMMEUES1APID_p, sizeof(MME_UE_S1AP_ID_t));
1389 s1apMMEUES1APID_p = NULL;
1390 } break;
1391 default:
1392 {
1393 log_msg(LOG_WARNING, "Unhandled IE %d\n", ie_p->id);
1394 }
1395 }
1396 }
1397 }
1398
1399 return 0;
1400}
1401
1402int convertUeCtxRelReqToProtoIe(InitiatingMessage_t *msg, struct proto_IE* proto_ies)
1403{
1404 proto_ies->procedureCode = msg->procedureCode;
1405 proto_ies->criticality = msg->criticality;
1406 int no_of_IEs = 0;
1407
1408 if(msg->value.present == InitiatingMessage__value_PR_UEContextReleaseRequest)
1409 {
1410 ProtocolIE_Container_129P23_t* protocolIes
1411 = &msg->value.choice.UEContextReleaseRequest.protocolIEs;
1412 no_of_IEs = protocolIes->list.count;
1413 proto_ies->no_of_IEs = no_of_IEs;
1414
1415 log_msg(LOG_INFO, "No of IEs = %d\n", no_of_IEs);
1416 proto_ies->data = calloc(sizeof(struct proto_IE_data), no_of_IEs);
1417 if(proto_ies->data == NULL)
1418 {
1419 log_msg(LOG_ERROR,"Malloc failed for protocol IE.");
1420 return -1;
1421 }
1422 for (int i = 0; i < protocolIes->list.count; i++) {
1423 UEContextReleaseRequest_IEs_t *ie_p;
1424 ie_p = protocolIes->list.array[i];
1425 switch(ie_p->id) {
1426 case ProtocolIE_ID_id_eNB_UE_S1AP_ID:
1427 {
1428 ENB_UE_S1AP_ID_t *s1apENBUES1APID_p = NULL;
1429 if(UEContextReleaseRequest_IEs__value_PR_ENB_UE_S1AP_ID == ie_p->value.present)
1430 {
1431 s1apENBUES1APID_p = &ie_p->value.choice.ENB_UE_S1AP_ID;
1432 }
1433
1434 if (s1apENBUES1APID_p == NULL) {
1435 log_msg (LOG_ERROR, "Decoding of IE eNB_UE_S1AP_ID failed\n");
1436 return -1;
1437 }
1438
1439 proto_ies->data[i].IE_type = S1AP_IE_ENB_UE_ID;
1440 memcpy(&proto_ies->data[i].val.enb_ue_s1ap_id, s1apENBUES1APID_p, sizeof(ENB_UE_S1AP_ID_t));
1441 s1apENBUES1APID_p = NULL;
1442 } break;
1443 case ProtocolIE_ID_id_MME_UE_S1AP_ID:
1444 {
1445 MME_UE_S1AP_ID_t *s1apMMEUES1APID_p = NULL;
1446 if(UEContextReleaseRequest_IEs__value_PR_MME_UE_S1AP_ID == ie_p->value.present)
1447 {
1448 s1apMMEUES1APID_p = &ie_p->value.choice.MME_UE_S1AP_ID;
1449 }
1450
1451 if (s1apMMEUES1APID_p == NULL) {
1452 log_msg (LOG_ERROR, "Decoding of IE MME_UE_S1AP_ID failed\n");
1453 return -1;
1454 }
1455
1456 proto_ies->data[i].IE_type = S1AP_IE_MME_UE_ID;
1457 memcpy(&proto_ies->data[i].val.mme_ue_s1ap_id, s1apMMEUES1APID_p, sizeof(MME_UE_S1AP_ID_t));
1458 s1apMMEUES1APID_p = NULL;
1459 } break;
1460 case ProtocolIE_ID_id_Cause:
1461 {
1462 Cause_t *s1apCause_p = NULL;
1463 if(UEContextReleaseRequest_IEs__value_PR_Cause == ie_p->value.present)
1464 {
1465 s1apCause_p = &ie_p->value.choice.Cause;
1466 }
1467
1468 if (s1apCause_p == NULL) {
1469 log_msg (LOG_ERROR, "Decoding of IE Cause failed\n");
1470 return -1;
1471 }
1472
1473 proto_ies->data[i].IE_type = S1AP_IE_CAUSE;
1474 proto_ies->data[i].val.cause.present = s1apCause_p->present;
1475 switch(s1apCause_p->present)
1476 {
1477 case Cause_PR_radioNetwork:
1478 log_msg (LOG_DEBUG, "RadioNetwork case : %d\n",
1479 s1apCause_p->choice.radioNetwork);
1480 proto_ies->data[i].val.cause.choice.radioNetwork
1481 = s1apCause_p->choice.radioNetwork;
1482 break;
1483 case Cause_PR_transport:
1484 log_msg (LOG_DEBUG, "Transport case : %d\n",
1485 s1apCause_p->choice.transport);
1486 proto_ies->data[i].val.cause.choice.transport
1487 = s1apCause_p->choice.transport;
1488 break;
1489 case Cause_PR_nas:
1490 log_msg (LOG_DEBUG, "Nas case : %d\n",
1491 s1apCause_p->choice.nas);
1492 proto_ies->data[i].val.cause.choice.nas
1493 = s1apCause_p->choice.nas;
1494 break;
1495 case Cause_PR_protocol:
1496 log_msg (LOG_DEBUG, "Protocol case : %d\n",
1497 s1apCause_p->choice.protocol);
1498 proto_ies->data[i].val.cause.choice.protocol
1499 = s1apCause_p->choice.protocol;
1500 break;
1501 case Cause_PR_misc:
1502 log_msg (LOG_DEBUG, "Misc case : %d\n",
1503 s1apCause_p->choice.misc);
1504 proto_ies->data[i].val.cause.choice.misc
1505 = s1apCause_p->choice.misc;
1506 break;
1507 case Cause_PR_NOTHING:
1508 default:
1509 log_msg(LOG_WARNING, "Unknown cause %d\n", s1apCause_p->present);
1510
1511 }
1512 s1apCause_p = NULL;
1513 } break;
1514 default:
1515 {
1516 log_msg(LOG_WARNING, "Unhandled IE %d\n", ie_p->id);
1517 }
1518 }
1519 }
1520 }
1521
1522 return 0;
1523}
1524