blob: 78b87611f907fd2e5b821953fa2e9abc36a38853 [file] [log] [blame]
anjana_sreekumar@infosys.com991c2062020-01-08 11:42:57 +05301/*
2 * Copyright 2019-present Infosys Limited
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7/******************************************************************************
8 *
9 * This file has both generated and manual code.
10 *
11 * File template used for code generation:
12 * <TOP-DIR/scripts/SMCodeGen/templates/stateMachineTmpls/actionHandlers.cpp.tt>
13 *
14 ******************************************************************************/
15
16#include <3gpp_24008.h>
17#include <typeinfo>
18#include "actionHandlers/actionHandlers.h"
19#include "controlBlock.h"
20#include "msgType.h"
21#include "contextManager/subsDataGroupManager.h"
22#include "contextManager/dataBlocks.h"
23#include "procedureStats.h"
24#include "log.h"
25#include "secUtils.h"
26#include "state.h"
27#include <string.h>
28#include <sstream>
29#include <smTypes.h>
30#include <cstring>
31#include <event.h>
32#include <ipcTypes.h>
33#include <tipcTypes.h>
34#include <msgBuffer.h>
35#include <interfaces/mmeIpcInterface.h>
36#include <utils/mmeCommonUtils.h>
37#include <utils/mmeContextManagerUtils.h>
38
39using namespace SM;
40using namespace mme;
41using namespace cmn::utils;
42
43extern MmeIpcInterface* mmeIpcIf_g;
44
45ActStatus ActionHandlers::validate_imsi_in_ue_context(ControlBlock& cb)
46{
47 UEContext* ueCtxt_p = static_cast<UEContext*>(cb.getPermDataBlock());
48 if (ueCtxt_p == NULL)
49 {
50 log_msg(LOG_DEBUG, "send_identity_request_to_ue: ue context is NULL \n");
51 return ActStatus::HALT;
52 }
53
54 if (ueCtxt_p->getImsi().isValid())
55 {
56 SM::Event evt(Event_e::IMSI_VALIDATION_SUCCESS, NULL);
57 cb.addEventToProcQ(evt);
58 }
59 else
60 {
61 // TODO: If known GUTI, IMSI_VALIDATION_FAILURE_KNOWN_GUTI to trigger id req to UE
62 // If unknown GUTI, IMSI_VALIDATION_FAILURE_UNKNOWN_GUTI to query old mme
63 // when s10 is supported in MME
64 SM::Event evt(Event_e::IMSI_VALIDATION_FAILURE, NULL);
65 cb.addEventToProcQ(evt);
66 }
67 return ActStatus::PROCEED;
68}
69
70ActStatus ActionHandlers::send_identity_request_to_ue(ControlBlock& cb)
71{
72 log_msg(LOG_DEBUG, "Inside send_identity_request_to_ue \n");
73
74 UEContext* ueCtxt_p = static_cast<UEContext*>(cb.getPermDataBlock());
75 if (ueCtxt_p == NULL)
76 {
77 log_msg(LOG_DEBUG, "send_identity_request_to_ue: ue context is NULL \n");
78 return ActStatus::HALT;
79 }
80
81 struct attachIdReq_info idReqMsg;
82 idReqMsg.msg_type = id_request;
83 idReqMsg.enb_fd = ueCtxt_p->getEnbFd();
84 idReqMsg.s1ap_enb_ue_id = ueCtxt_p->getS1apEnbUeId();
85 idReqMsg.ue_idx = ueCtxt_p->getContextID();
86 idReqMsg.ue_type = ID_IMSI;
87
88 cmn::ipc::IpcAddress destAddr;
89 destAddr.u32 = TipcServiceInstance::s1apAppInstanceNum_c;
90
91 mmeIpcIf_g->dispatchIpcMsg((char *) &idReqMsg, sizeof(idReqMsg), destAddr);
92
93 return ActStatus::PROCEED;
94}
95
96ActStatus ActionHandlers::process_identity_response(ControlBlock& cb)
97{
98 log_msg(LOG_DEBUG, "Inside process_identity_response \n");
99
100 UEContext *ueCtxt_p = static_cast<UEContext*>(cb.getPermDataBlock());
101 if (ueCtxt_p == NULL)
102 {
103 log_msg(LOG_DEBUG, "process_identity_response: ue context is NULL \n");
104 return ActStatus::HALT;
105 }
106
107 MsgBuffer* msgBuf = static_cast<MsgBuffer*>(cb.getMsgData());
108 if (msgBuf == NULL)
109 {
110 log_msg(LOG_DEBUG, "process_identity_response: msgBuf is NULL \n");
111 return ActStatus::HALT;
112 }
113
114 const s1_incoming_msg_data_t* s1_msg_data = static_cast<const s1_incoming_msg_data_t*>(msgBuf->getDataPointer());
115 if (s1_msg_data == NULL)
116 {
117 log_msg(LOG_DEBUG, "process_identity_response: s1MsgData is NULL \n");
118 return ActStatus::HALT;
119 }
120
121 const struct identityResp_Q_msg &id_resp = s1_msg_data->msg_data.identityResp_Q_msg_m;
122 if(SUCCESS != id_resp.status)
123 {
124 log_msg(LOG_DEBUG, "process_identity_response: ID Response Failure NULL \n");
125 return ActStatus::HALT;
126 }
127
128 uint8_t imsi[BINARY_IMSI_LEN] = {0};
129 memcpy( imsi, id_resp.IMSI, BINARY_IMSI_LEN );
130
131 // Only upper nibble of first octect in imsi need to be considered
132 // Changing the lower nibble to 0x0f for handling
133 uint8_t first = imsi[0] >> 4;
134 imsi[0] = (uint8_t)(( first << 4 ) | 0x0f );
135
136 DigitRegister15 IMSIInfo;
137 IMSIInfo.convertFromBcdArray(imsi);
138 ueCtxt_p->setImsi(IMSIInfo);
139
140 SubsDataGroupManager::Instance()->addimsikey(ueCtxt_p->getImsi(), ueCtxt_p->getContextID());
141
142 return ActStatus::PROCEED;
143}
144
145
146ActStatus ActionHandlers::send_air_to_hss(SM::ControlBlock& cb)
147{
148 log_msg(LOG_DEBUG, "Inside send_air_to_hss \n");
149
150 UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
151 if (ue_ctxt == NULL)
152 {
153 log_msg(LOG_DEBUG, "send_air_to_hss: ue context is NULL \n");
154 return ActStatus::HALT;
155 }
156
157 s6a_Q_msg s6a_req;
158
159 memset(s6a_req.imsi, '\0', sizeof(s6a_req.imsi));
160 ue_ctxt->getImsi().getImsiDigits(s6a_req.imsi);
161
162 memcpy(&(s6a_req.tai), &(ue_ctxt->getTai().tai_m), sizeof(struct TAI));
163
164 s6a_req.ue_idx = ue_ctxt->getContextID();
165 s6a_req.msg_type = auth_info_request;
166
167 cmn::ipc::IpcAddress destAddr;
168 destAddr.u32 = TipcServiceInstance::s6AppInstanceNum_c;
169
170 mmeIpcIf_g->dispatchIpcMsg((char *) &s6a_req, sizeof(s6a_req), destAddr);
171
172 ProcedureStats::num_of_air_sent ++;
173 log_msg(LOG_DEBUG, "Leaving send_air_to_hss \n");
174
175 return ActStatus::PROCEED;
176
177}
178
179ActStatus ActionHandlers::send_ulr_to_hss(SM::ControlBlock& cb)
180{
181 log_msg(LOG_DEBUG, "Inside send_ulr_to_hss \n");
182
183 UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
184 if (ue_ctxt == NULL)
185 {
186 log_msg(LOG_DEBUG, "send_ulr_to_hss: ue context is NULL \n");
187 return ActStatus::HALT;
188 }
189
190 s6a_Q_msg s6a_req;
191
192 memset(s6a_req.imsi, '\0', sizeof(s6a_req.imsi));
193 ue_ctxt->getImsi().getImsiDigits(s6a_req.imsi);
194
195 memcpy(&(s6a_req.tai), &(ue_ctxt->getTai().tai_m), sizeof(struct TAI));
196
197 s6a_req.ue_idx = ue_ctxt->getContextID();
198 s6a_req.msg_type = update_loc_request;
199
200 cmn::ipc::IpcAddress destAddr;
201 destAddr.u32 = TipcServiceInstance::s6AppInstanceNum_c;
202
203 mmeIpcIf_g->dispatchIpcMsg((char *) &s6a_req, sizeof(s6a_req), destAddr);
204
205 ProcedureStats::num_of_ulr_sent ++;
206 log_msg(LOG_DEBUG, "Leaving send_ulr_to_hss \n");
207
208 return ActStatus::PROCEED;
209}
210
211
212ActStatus ActionHandlers::process_aia(SM::ControlBlock& cb)
213{
214 log_msg(LOG_DEBUG, "Inside handle_aia \n");
215
216 UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
217 if (ue_ctxt == NULL)
218 {
219 log_msg(LOG_DEBUG, "handle_aia: ue context is NULL \n");
220 return ActStatus::HALT;
221 }
222
223 MsgBuffer* msgBuf = static_cast<MsgBuffer*>(cb.getMsgData());
224
225 if (msgBuf == NULL)
226 return ActStatus::HALT;
227
228 const s6_incoming_msg_data_t* msgData_p = static_cast<const s6_incoming_msg_data_t*>(msgBuf->getDataPointer());
229
230 ue_ctxt->setAiaSecInfo(E_utran_sec_vector(msgData_p->msg_data.aia_Q_msg_m.sec));
231
232 ProcedureStats::num_of_processed_aia ++;
233 log_msg(LOG_DEBUG, "Leaving handle_aia \n");
234
235 return ActStatus::PROCEED;
236}
237
238ActStatus ActionHandlers::process_ula(SM::ControlBlock& cb)
239{
240 log_msg(LOG_DEBUG, "Inside handle_ula \n");
241
242 UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
243 if (ue_ctxt == NULL)
244 {
245 log_msg(LOG_DEBUG, "handle_ula: ue context is NULL \n");
246 return ActStatus::HALT;
247 }
248
249 SessionContext* sessionCtxt = ue_ctxt->getSessionContext();
250 if( sessionCtxt == NULL )
251 {
252 log_msg(LOG_ERROR, "Failed to retrieve Session Context for UE IDX %d\n", cb.getCBIndex());
253 return ActStatus::HALT;
254 }
255
256 MsgBuffer* msgBuf = static_cast<MsgBuffer*>(cb.getMsgData());
257
258 if (msgBuf == NULL)
259 return ActStatus::HALT;
260
261 const s6_incoming_msg_data_t* s6_msg_data = static_cast<const s6_incoming_msg_data_t*>(msgBuf->getDataPointer());
262 const struct ula_Q_msg &ula_msg = s6_msg_data->msg_data.ula_Q_msg_m;
263
264 sessionCtxt->setApnConfigProfileCtxId(ula_msg.apn_config_profile_ctx_id);
265 DigitRegister15 ueMSISDN;
266 ueMSISDN.convertFromBcdArray( reinterpret_cast<const uint8_t*>( ula_msg.MSISDN ));
267 ue_ctxt->setMsisdn(ueMSISDN);
268 ue_ctxt->setRauTauTimer(ula_msg.RAU_TAU_timer);
269 ue_ctxt->setSubscriptionStatus(ula_msg.subscription_status);
270 ue_ctxt->setNetAccessMode(ula_msg.net_access_mode);
271 ue_ctxt->setAccessRestrictionData(ula_msg.access_restriction_data);
272
273 struct AMBR ambr;
274 ambr.max_requested_bw_dl = ula_msg.max_requested_bw_dl;
275 ambr.max_requested_bw_ul = ula_msg.max_requested_bw_ul;
276
277 ue_ctxt->setAmbr(Ambr(ambr));
278
279 ProcedureStats::num_of_processed_ula ++;
280 log_msg(LOG_DEBUG, "Leaving handle_ula_v \n");
281
282 return ActStatus::PROCEED;
283}
284
285ActStatus ActionHandlers::auth_req_to_ue(SM::ControlBlock& cb)
286{
287 UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
288
289 if (ue_ctxt == NULL)
290 {
291 log_msg(LOG_DEBUG, "auth_req_to_ue: ue context is NULL \n");
292 return ActStatus::HALT;
293 }
294
295 authreq_info authreq;
296 authreq.msg_type = auth_request;
297 authreq.ue_idx = ue_ctxt->getContextID();
298 authreq.enb_fd = ue_ctxt->getEnbFd();
299 authreq.enb_s1ap_ue_id = ue_ctxt->getS1apEnbUeId();
300
301 ue_ctxt->setDwnLnkSeqNo(0);
302
303 E_UTRAN_sec_vector *secVect = const_cast<E_UTRAN_sec_vector*>(ue_ctxt->getAiaSecInfo().AiaSecInfo_mp);
304
305 secinfo& secInfo = const_cast<secinfo&>(ue_ctxt->getUeSecInfo().secinfo_m);
306
307 SecUtils::create_integrity_key(secVect->kasme.val, secInfo.int_key);
308
309 memcpy(&(authreq.rand), &(secVect->rand.val), NAS_RAND_SIZE);
310 memcpy(&(authreq.autn), &(secVect->autn.val), NAS_AUTN_SIZE);
311
312 cmn::ipc::IpcAddress destAddr;
313 destAddr.u32 = TipcServiceInstance::s1apAppInstanceNum_c;
314
315 mmeIpcIf_g->dispatchIpcMsg((char *) &authreq, sizeof(authreq), destAddr);
316
317
318 ProcedureStats::num_of_auth_req_to_ue_sent ++;
319 log_msg(LOG_DEBUG, "Leaving auth_req_to_ue_v \n");
320
321 return ActStatus::PROCEED;
322}
323
324ActStatus ActionHandlers::auth_response_validate(SM::ControlBlock& cb)
325{
326 log_msg(LOG_DEBUG, "Inside auth_response_validate \n");
327 SM::ControlBlock* controlBlk_p = SubsDataGroupManager::Instance()->findControlBlock(cb.getCBIndex());
328
329 UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
330 if (ue_ctxt == NULL)
331 {
332 log_msg(LOG_DEBUG, "auth_response_validate: ue context or procedure ctxt is NULL \n");
333 return ActStatus::HALT;
334 }
335
336 MsgBuffer* msgBuf = static_cast<MsgBuffer*>(cb.getMsgData());
337
338 if (msgBuf == NULL)
339 return ActStatus::HALT;
340
341 const s1_incoming_msg_data_t* s1_msg_data = static_cast<const s1_incoming_msg_data_t*>(msgBuf->getDataPointer());
342 const struct authresp_Q_msg &auth_resp = s1_msg_data->msg_data.authresp_Q_msg_m;
343
344 /*Check the state*/
345 if(SUCCESS != auth_resp.status) {
346 log_msg(LOG_ERROR, "eNB authentication failure for UE-%d.\n", ue_ctxt->getContextID());
347 if(auth_resp.auts.len == 0)
348 {
349 log_msg(LOG_ERROR,"No AUTS.Not Synch Failure\n");
350 SM::Event evt(Event_e::AUTH_RESP_FAILURE,NULL);
351 controlBlk_p->addEventToProcQ(evt);
352 }
353 else
354 {
355 log_msg(LOG_INFO,"AUTS recvd. Synch failure. send AIR\n");
356 SM::Event evt(Event_e::AUTH_RESP_SYNC_FAILURE,NULL);
357 controlBlk_p->addEventToProcQ(evt);
358 }
359 }
360 else{
361 log_msg(LOG_INFO,"Auth response validation success. Proceeding to Sec mode Command\n");
362 SM::Event evt(Event_e::AUTH_RESP_SUCCESS,NULL);
363 controlBlk_p->addEventToProcQ(evt);
364
365 }
366 //TODO: XRES comparison
367 #if 0
368 log_msg(LOG_ERROR, "stage 3 processing memcmp - %d, %d, %d", &(ue_ctxt->getaiaSecInfo().AiaSecInfo_mp->xres.val),
369 &(auth_resp->res.val),
370 auth_resp->res.len);
371 if(memcmp(&(ue_ctxt->getaiaSecInfo().AiaSecInfo_mp->xres.val),
372 &(auth_resp->res.val),
373 auth_resp->res.len) != 0) {
374 log_msg(LOG_ERROR, "Invalid auth result received for UE %d",
375 auth_resp->ue_idx);
376 return E_FAIL;//report failure
377 }
378 #endif
379
380 ProcedureStats::num_of_processed_auth_response ++;
381 log_msg(LOG_DEBUG, "Leaving auth_response_validate \n");
382
383 return ActStatus::PROCEED;
384}
385
386ActStatus ActionHandlers::send_auth_reject(SM::ControlBlock& cb)
387{
388 log_msg(LOG_DEBUG, "Inside send_auth_reject \n");
389
390 UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
391 if (ue_ctxt == NULL)
392 {
393 log_msg(LOG_DEBUG, "send_auth_reject: ue context is NULL \n");
394 return ActStatus::HALT;
395 }
396 return ActStatus::HALT;
397}
398
399
400ActStatus ActionHandlers::sec_mode_cmd_to_ue(SM::ControlBlock& cb)
401{
402 log_msg(LOG_DEBUG, "Inside sec_mode_cmd_to_ue \n");
403
404 UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
405 if (ue_ctxt == NULL)
406 {
407 log_msg(LOG_DEBUG, "sec_mode_cmd_to_ue: ue context is NULL \n");
408 return ActStatus::HALT;
409 }
410 sec_mode_Q_msg sec_mode_msg;
411 sec_mode_msg.msg_type = sec_mode_command;
412 sec_mode_msg.ue_idx = ue_ctxt->getContextID();
413 sec_mode_msg.enb_fd = ue_ctxt->getEnbFd();
414 sec_mode_msg.enb_s1ap_ue_id = ue_ctxt->getS1apEnbUeId();
415
416 memcpy(&(sec_mode_msg.ue_network), &(ue_ctxt->getUeNetCapab().ue_net_capab_m),
417 sizeof(struct UE_net_capab));
418
419 memcpy(&(sec_mode_msg.ms_net_capab), &(ue_ctxt->getMsNetCapab().ms_net_capab_m),
420 sizeof(struct MS_net_capab));
421
422 memcpy(&(sec_mode_msg.key), &(ue_ctxt->getAiaSecInfo().AiaSecInfo_mp->kasme),
423 sizeof(struct KASME));
424
425 memcpy(&(sec_mode_msg.int_key), &(ue_ctxt->getUeSecInfo().secinfo_m.int_key),
426 NAS_INT_KEY_SIZE);
427
428 sec_mode_msg.dl_seq_no = ue_ctxt->getDwnLnkSeqNo();
429 ue_ctxt->setDwnLnkSeqNo(sec_mode_msg.dl_seq_no + 1);
430
431 cmn::ipc::IpcAddress destAddr;
432 destAddr.u32 = TipcServiceInstance::s1apAppInstanceNum_c;
433
434 mmeIpcIf_g->dispatchIpcMsg((char *) &sec_mode_msg, sizeof(sec_mode_msg), destAddr);
435
436 ProcedureStats::num_of_sec_mode_cmd_to_ue_sent ++;
437 log_msg(LOG_DEBUG, "Leaving sec_mode_cmd_to_ue \n");
438
439 return ActStatus::PROCEED;
440}
441
442
443ActStatus ActionHandlers::process_sec_mode_resp(SM::ControlBlock& cb)
444{
445 log_msg(LOG_DEBUG, "Inside handle_sec_mode_resp \n");
446
447 UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
448 if (ue_ctxt == NULL)
449 {
450 log_msg(LOG_DEBUG, "handle_sec_mode_resp: ue context is NULL \n");
451 return ActStatus::HALT;
452 }
453
454 MsgBuffer* msgBuf = static_cast<MsgBuffer*>(cb.getMsgData());
455
456 if (msgBuf == NULL)
457 return ActStatus::HALT;
458
459 const s1_incoming_msg_data_t* s1_msg_data = static_cast<const s1_incoming_msg_data_t*>(msgBuf->getDataPointer());
460 const secmode_resp_Q_msg &secmode_resp = s1_msg_data->msg_data.secmode_resp_Q_msg_m;
461 if(SUCCESS == secmode_resp.status)
462 {
463 log_msg(LOG_INFO, "Sec mode complete rcv. UE - %d.\n",
464 ue_ctxt->getContextID());
465
466 }
467 else
468 {
469 log_msg(LOG_INFO, "Sec mode failed. UE %d", ue_ctxt->getContextID());
470 }
471
472 ProcedureStats::num_of_processed_sec_mode_resp ++;
473 log_msg(LOG_DEBUG, "Leaving handle_sec_mode_resp \n");
474
475 return ActStatus::PROCEED;
476}
477
478ActStatus ActionHandlers::check_esm_info_req_required(SM::ControlBlock& cb)
479{
480 log_msg(LOG_DEBUG, "Inside check_esm_info_req_required \n");
481
482 UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
483 if (ue_ctxt == NULL)
484 {
485 log_msg(LOG_DEBUG, "check_esm_info_req_required: ue context is NULL \n");
486 return ActStatus::HALT;
487 }
488
489 MmeProcedureCtxt* procedure_p = dynamic_cast<MmeProcedureCtxt*>(cb.getTempDataBlock());
490 if (procedure_p == NULL)
491 {
492 log_msg(LOG_DEBUG, "check_esm_info_req_required: procedure context is NULL \n");
493 return ActStatus::HALT;
494 }
495 SessionContext* sessionCtxt = SubsDataGroupManager::Instance()->getSessionContext();
496 if( sessionCtxt == NULL )
497 {
498 log_msg(LOG_ERROR, "Failed to allocate Session Context for UE IDX %d\n", cb.getCBIndex());
499
500 return ActStatus::HALT;
501 }
502 BearerContext* bearerCtxt_p = SubsDataGroupManager::Instance()->getBearerContext();
503 if( bearerCtxt_p == NULL )
504 {
505 log_msg(LOG_ERROR, "Failed to allocate Bearer context for UE IDx %d\n", cb.getCBIndex());
506
507 return ActStatus::HALT;
508 }
509
510 bearerCtxt_p->setBearerId(5);
511 sessionCtxt->setPti(procedure_p->getPti());
512 sessionCtxt->setBearerContext( bearerCtxt_p );
513 ue_ctxt->setSessionContext(sessionCtxt);
514
515 if (procedure_p->getEsmInfoTxRequired() == false)
516 {
517 // hardcoding APN, if ESM info request is not to be sent
518 std::string apnName = "apn1";
519 struct apn_name apn = {0};
520 apn.len = apnName.length() + 1;
521 apn.val[0] = apnName.length();
522 memcpy(&(apn.val[1]), apnName.c_str(), apnName.length());
523
524 sessionCtxt->setAccessPtName(Apn_name(apn));
525
526 SM::Event evt(Event_e::ESM_INFO_NOT_REQUIRED, NULL);
527 cb.addEventToProcQ(evt);
528 }
529 else
530 {
531 SM::Event evt(Event_e::ESM_INFO_REQUIRED, NULL);
532 cb.addEventToProcQ(evt);
533 }
534
535 return ActStatus::PROCEED;
536}
537
538ActStatus ActionHandlers::send_esm_info_req_to_ue(SM::ControlBlock& cb)
539{
540 UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
541
542 if (ue_ctxt == NULL)
543 {
544 log_msg(LOG_DEBUG, "send_esm_info_req_to_ue: ue context is NULL \n");
545 return ActStatus::HALT;
546 }
547
548 SessionContext *sessionCtxt = ue_ctxt->getSessionContext();
549 esm_req_Q_msg esmreq;
550 esmreq.msg_type = esm_info_request;
551 esmreq.ue_idx = ue_ctxt->getContextID();
552 esmreq.enb_fd = ue_ctxt->getEnbFd();
553 esmreq.enb_s1ap_ue_id = ue_ctxt->getS1apEnbUeId();
554 esmreq.pti = sessionCtxt->getPti();
555 esmreq.dl_seq_no = ue_ctxt->getDwnLnkSeqNo();
556 memcpy(&(esmreq.int_key), &((ue_ctxt->getUeSecInfo().secinfo_m).int_key),
557 NAS_INT_KEY_SIZE);
558 ue_ctxt->setDwnLnkSeqNo(esmreq.dl_seq_no+1);
559
560 cmn::ipc::IpcAddress destAddr;
561 destAddr.u32 = TipcServiceInstance::s1apAppInstanceNum_c;
562
563 mmeIpcIf_g->dispatchIpcMsg((char *) &esmreq, sizeof(esmreq), destAddr);
564
565 log_msg(LOG_DEBUG, "Leaving send_esm_info_req_to_ue \n");
566
567 return ActStatus::PROCEED;
568}
569
570ActStatus ActionHandlers::process_esm_info_resp(SM::ControlBlock& cb)
571{
572 UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
573 if (ue_ctxt == NULL)
574 {
575 log_msg(LOG_DEBUG, "handle_ula: ue context is NULL \n");
576 return ActStatus::HALT;
577 }
578
579 SessionContext* sessionCtxt = ue_ctxt->getSessionContext();
580 if( sessionCtxt == NULL )
581 {
582 log_msg(LOG_ERROR, "Failed to allocate Session "
583 "Context for UE IDX %d\n", cb.getCBIndex());
584 return ActStatus::HALT;
585 }
586
587 MsgBuffer* msgBuf = static_cast<MsgBuffer*>(cb.getMsgData());
588
589 if (msgBuf == NULL)
590 return ActStatus::HALT;
591
592 const s1_incoming_msg_data_t* s1_msg_data = static_cast<const s1_incoming_msg_data_t*>(msgBuf->getDataPointer());
593 const struct esm_resp_Q_msg &esm_res =s1_msg_data->msg_data.esm_resp_Q_msg_m;
594
595 sessionCtxt->setAccessPtName(Apn_name(esm_res.apn));
596
597 return ActStatus::PROCEED;
598}
599
600ActStatus ActionHandlers::cs_req_to_sgw(SM::ControlBlock& cb)
601{
602 log_msg(LOG_DEBUG, "Inside cs_req_to_sgw \n");
603
604 UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
605 MmeProcedureCtxt *procCtxt = dynamic_cast<MmeProcedureCtxt*>(cb.getTempDataBlock());
606 if (ue_ctxt == NULL || procCtxt == NULL)
607 {
608 log_msg(LOG_DEBUG, "handle_ula: UE context or Procedure Context is NULL \n");
609
610 return ActStatus::HALT;
611 }
612
613 SessionContext* sessionCtxt = ue_ctxt->getSessionContext();
614 if( sessionCtxt == NULL )
615 {
616 log_msg(LOG_ERROR, "Failed to allocate Session Context for UE IDX %d\n", cb.getCBIndex());
617
618 return ActStatus::HALT;
619 }
620
621 BearerContext* bearerCtxt_p = sessionCtxt->getBearerContext();
622 if( bearerCtxt_p == NULL )
623 {
624 log_msg(LOG_ERROR, "Failed to allocate Bearer context for UE IDx %d\n", cb.getCBIndex());
625
626 return ActStatus::HALT;
627 }
628
629 struct CS_Q_msg cs_msg;
630 cs_msg.msg_type = create_session_request;
631 cs_msg.ue_idx = ue_ctxt->getContextID();
632
633 const DigitRegister15& ueImsi = ue_ctxt->getImsi();
634 ueImsi.convertToBcdArray( cs_msg.IMSI );
635
636 /*uint8_t plmn_id[3] = {0};
637 memcpy(plmn_id, ue_ctxt->gettai().tai_m.plmn_id.idx, 3);
638 if ((plmn_id[1] & 0xF0) == 0xF0)
639 plmn_id[1] = plmn_id[1] & 0x0F;
640
641 const Apn_name &apnName = sessionCtxt->getaccessPtName();
642 std::string apnStr((const char *)apnName.apnname_m.val, apnName.apnname_m.len);
643
644 stringstream formattedApn;
645 formattedApn << apnStr <<
646 "\x6" << "mnc" <<
647 ((plmn_id[1] & 0xF0) >> 4) <<
648 (plmn_id[2] & 0x0F) <<
649 ((plmn_id[2] & 0xF0) >> 4) <<
650 "\x6" << "mcc" <<
651 (plmn_id[0] & 0x0F) <<
652 ((plmn_id[0] & 0xF0) >> 4) <<
653 ((plmn_id[1] & 0x0F)) <<
654 "\x4" << "gprs";
655
656 uint32_t formattedApnLen = formattedApn.str().length();
657 cs_msg.apn.len = formattedApnLen + 1;
658 cs_msg.apn.val[0] = apnStr.length();
659 memcpy(&cs_msg.apn.val[1], formattedApn.str().c_str(),
660 formattedApn.str().length()); */
661
662 const Apn_name &apnName = sessionCtxt->getAccessPtName();
663 memcpy(&(cs_msg.apn), &(apnName.apnname_m), sizeof(struct apn_name));
664 memcpy(&(cs_msg.tai), &(ue_ctxt->getTai().tai_m), sizeof(struct TAI));
665 memcpy(&(cs_msg.utran_cgi), &(ue_ctxt->getUtranCgi().cgi_m), sizeof(struct CGI));
666 memcpy(&(cs_msg.pco_options[0]), procCtxt->getPcoOptions(),sizeof(cs_msg.pco_options));
667
668 const AMBR& ambr = ue_ctxt->getAmbr().ambr_m;
669
670 cs_msg.max_requested_bw_dl = ambr.max_requested_bw_dl;
671 cs_msg.max_requested_bw_ul = ambr.max_requested_bw_ul;
672
673 memset(cs_msg.MSISDN, 0, BINARY_IMSI_LEN);
674
675 const DigitRegister15& ueMSISDN = ue_ctxt->getMsisdn();
676 ueMSISDN.convertToBcdArray(cs_msg.MSISDN);
677
678 cmn::ipc::IpcAddress destAddr;
679 destAddr.u32 = TipcServiceInstance::s11AppInstanceNum_c;
680
681 mmeIpcIf_g->dispatchIpcMsg((char *) &cs_msg, sizeof(cs_msg), destAddr);
682
683 ProcedureStats::num_of_cs_req_to_sgw_sent ++;
684 log_msg(LOG_DEBUG, "Leaving cs_req_to_sgw \n");
685
686 return ActStatus::PROCEED;
687}
688
689ActStatus ActionHandlers::process_cs_resp(SM::ControlBlock& cb)
690{
691 log_msg(LOG_DEBUG, "Entering handle_cs_resp \n");
692
693 UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
694 if (ue_ctxt == NULL)
695 {
696 log_msg(LOG_DEBUG, "handle_cs_resp: ue context is NULL \n");
697 return ActStatus::HALT;
698 }
699
700 SessionContext* sessionCtxt = ue_ctxt->getSessionContext();
701 if (sessionCtxt == NULL)
702 {
703 log_msg(LOG_DEBUG, "handle_cs_resp: session ctxt is NULL \n");
704 return ActStatus::HALT;
705 }
706
707 MsgBuffer* msgBuf = static_cast<MsgBuffer*>(cb.getMsgData());
708
709 if (msgBuf == NULL)
710 return ActStatus::HALT;
711
712 const gtp_incoming_msg_data_t* gtp_msg_data= static_cast<const gtp_incoming_msg_data_t*>(msgBuf->getDataPointer());
713 const struct csr_Q_msg& csr_info = gtp_msg_data->msg_data.csr_Q_msg_m;
714
715 BearerContext* bearerCtxt = sessionCtxt->getBearerContext();
716 if( bearerCtxt == NULL )
717 {
718 log_msg(LOG_ERROR, "Failed to retrive Bearer context for UE IDx %d\n", cb.getCBIndex());
719
720 return ActStatus::HALT;
721 }
722
723 sessionCtxt->setS11SgwCtrlFteid(Fteid(csr_info.s11_sgw_fteid));
724 sessionCtxt->setS5S8PgwCtrlFteid(Fteid(csr_info.s5s8_pgwc_fteid));
725
726 bearerCtxt->setS1uSgwUserFteid(Fteid(csr_info.s1u_sgw_fteid));
727 bearerCtxt->setS5S8PgwUserFteid(Fteid(csr_info.s5s8_pgwu_fteid));
728
729 sessionCtxt->setPdnAddr(Paa(csr_info.pdn_addr));
730
731 ProcedureStats::num_of_processed_cs_resp ++;
732 log_msg(LOG_DEBUG, "Leaving handle_cs_resp \n");
733
734 return ActStatus::PROCEED;
735}
736
737ActStatus ActionHandlers::send_init_ctxt_req_to_ue(SM::ControlBlock& cb)
738{
739 log_msg(LOG_DEBUG, "Inside send_init_ctxt_req_to_ue \n");
740
741 UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
742 if (ue_ctxt == NULL )
743 {
744 log_msg(LOG_DEBUG, "send_init_ctxt_req_to_ue: ue context is NULL \n");
745 return ActStatus::HALT;
746 }
747
748 MmeProcedureCtxt* procedure_p = dynamic_cast<MmeProcedureCtxt*>(cb.getTempDataBlock());
749 if (procedure_p == NULL)
750 {
751 log_msg(LOG_DEBUG, "send_init_ctxt_req_to_ue: procedure context is NULL \n");
752 return ActStatus::HALT;
753 }
754
755 if (procedure_p->getAttachType() == imsiAttach_c ||
756 procedure_p->getAttachType() == unknownGutiAttach_c)
757 {
758 uint32_t mTmsi = MmeCommonUtils::allocateMtmsi();
759 if (mTmsi == 0)
760 {
761 log_msg(LOG_DEBUG, "send_init_ctxt_req_to_ue: Failed to allocate mTmsi \n");
762 return ActStatus::HALT;
763 }
764
765 ue_ctxt->setMtmsi(mTmsi);
766
767 // TODO: Should this be done here or attach_done method
768 SubsDataGroupManager::Instance()->addmTmsikey(mTmsi, ue_ctxt->getContextID());
769 }
770
771 SessionContext* sessionCtxt = ue_ctxt->getSessionContext();
772 if (sessionCtxt == NULL)
773 {
774 log_msg(LOG_DEBUG, "send_init_ctxt_req_to_ue: session ctxt is NULL \n");
775 return ActStatus::HALT;
776 }
777
778 unsigned int nas_count = 0;
779 E_UTRAN_sec_vector* secVect = const_cast<E_UTRAN_sec_vector*>(ue_ctxt->getAiaSecInfo().AiaSecInfo_mp);
780 secinfo& secInfo = const_cast<secinfo&>(ue_ctxt->getUeSecInfo().secinfo_m);
781
782 SecUtils::create_kenb_key(secVect->kasme.val, secInfo.kenb_key, nas_count);
783
784 init_ctx_req_Q_msg icr_msg;
785 icr_msg.msg_type = init_ctxt_request;
786 icr_msg.ue_idx = ue_ctxt->getContextID();
787 icr_msg.enb_fd = ue_ctxt->getEnbFd();
788 icr_msg.enb_s1ap_ue_id = ue_ctxt->getS1apEnbUeId();
789
790 icr_msg.exg_max_dl_bitrate = (ue_ctxt->getAmbr().ambr_m).max_requested_bw_dl;
791 icr_msg.exg_max_ul_bitrate = (ue_ctxt->getAmbr().ambr_m).max_requested_bw_ul;
792 BearerContext* bearerCtxt = sessionCtxt->getBearerContext();
793 if( bearerCtxt == NULL )
794 {
795 log_msg(LOG_ERROR, "Failed to retrive Bearer context for UE IDx %d\n", cb.getCBIndex());
796
797 return ActStatus::HALT;
798 }
799
800 icr_msg.bearer_id = bearerCtxt->getBearerId();
801
802 icr_msg.dl_seq_no = ue_ctxt->getDwnLnkSeqNo();
803 memcpy(&(icr_msg.tai), &(ue_ctxt->getTai().tai_m), sizeof(struct TAI));
804 memcpy(&(icr_msg.gtp_teid), &(bearerCtxt->getS1uSgwUserFteid().fteid_m), sizeof(struct fteid));
805 memcpy(&(icr_msg.apn), &(sessionCtxt->getAccessPtName().apnname_m), sizeof(struct apn_name));
806 memcpy(&(icr_msg.pdn_addr), &(sessionCtxt->getPdnAddr().paa_m), sizeof(struct PAA));
807 memcpy(&(icr_msg.int_key), &((ue_ctxt->getUeSecInfo().secinfo_m).int_key),
808 NAS_INT_KEY_SIZE);
809 memcpy(&(icr_msg.sec_key), &((ue_ctxt->getUeSecInfo().secinfo_m).kenb_key),
810 KENB_SIZE);
811 icr_msg.pti = sessionCtxt->getPti();
812 icr_msg.m_tmsi = ue_ctxt->getMtmsi();
813 ue_ctxt->setDwnLnkSeqNo(icr_msg.dl_seq_no+1);
814
815 cmn::ipc::IpcAddress destAddr;
816 destAddr.u32 = TipcServiceInstance::s1apAppInstanceNum_c;
817
818 mmeIpcIf_g->dispatchIpcMsg((char *) &icr_msg, sizeof(icr_msg), destAddr);
819
820 ProcedureStats::num_of_init_ctxt_req_to_ue_sent ++;
821 log_msg(LOG_DEBUG, "Leaving send_init_ctxt_req_to_ue_v \n");
822
823 return ActStatus::PROCEED;
824}
825
826ActStatus ActionHandlers::process_init_ctxt_resp(SM::ControlBlock& cb)
827{
828 log_msg(LOG_DEBUG, "Inside process_init_ctxt_resp \n");
829
830 UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
831 MmeProcedureCtxt *procCtxt = dynamic_cast<MmeProcedureCtxt*>(cb.getTempDataBlock());
832
833 if (ue_ctxt == NULL || procCtxt == NULL)
834 {
835 log_msg(LOG_DEBUG, "process_init_ctxt_resp: ue context or procedure ctxt is NULL \n");
836 return ActStatus::HALT;
837 }
838
839 SessionContext* sessionCtxt = ue_ctxt->getSessionContext();
840 if (sessionCtxt == NULL)
841 {
842 log_msg(LOG_DEBUG, "process_init_ctxt_resp: session ctxt is NULL \n");
843 return ActStatus::HALT;
844 }
845
846 MsgBuffer* msgBuf = static_cast<MsgBuffer*>(cb.getMsgData());
847
848 if (msgBuf == NULL)
849 return ActStatus::HALT;
850
851 const s1_incoming_msg_data_t* s1_msg_data = static_cast<const s1_incoming_msg_data_t*>(msgBuf->getDataPointer());
852 const struct initctx_resp_Q_msg &ics_res =s1_msg_data->msg_data.initctx_resp_Q_msg_m;
853
854 fteid S1uEnbUserFteid;
855 S1uEnbUserFteid.header.iface_type = 0;
856 S1uEnbUserFteid.header.v4 = 1;
857 S1uEnbUserFteid.header.teid_gre = ics_res.gtp_teid;
858 S1uEnbUserFteid.ip.ipv4 = *(struct in_addr*)&ics_res.transp_layer_addr;
859
860 BearerContext* bearerCtxt = sessionCtxt->getBearerContext();
861 if (bearerCtxt == NULL)
862 {
863 log_msg(LOG_DEBUG, "process_init_ctxt_resp: bearer ctxt is NULL \n");
864 return ActStatus::HALT;
865 }
866
867 bearerCtxt->setS1uEnbUserFteid(Fteid(S1uEnbUserFteid));
868
869 ProcedureStats::num_of_processed_init_ctxt_resp ++;
870 log_msg(LOG_DEBUG, "Leaving process_init_ctxt_resp \n");
871
872 return ActStatus::PROCEED;
873}
874
875ActStatus ActionHandlers::send_mb_req_to_sgw(SM::ControlBlock& cb)
876{
877 log_msg(LOG_DEBUG, "Inside send_mb_req_to_sgw \n");
878
879 UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
880 if (ue_ctxt == NULL)
881 {
882 log_msg(LOG_DEBUG, "send_mb_req_to_sgw: ue context or procedure ctxt is NULL \n");
883 return ActStatus::HALT;
884 }
885
886 SessionContext* sessionCtxt = ue_ctxt->getSessionContext();
887 if (sessionCtxt == NULL)
888 {
889 log_msg(LOG_DEBUG, "send_mb_req_to_sgw: session ctxt is NULL \n");
890 return ActStatus::HALT;
891 }
892
893 struct MB_Q_msg mb_msg;
894 mb_msg.msg_type = modify_bearer_request;
895 mb_msg.ue_idx = ue_ctxt->getContextID();
896
897 memset(mb_msg.indication, 0, S11_MB_INDICATION_FLAG_SIZE); /*TODO : future*/
898 BearerContext* bearerCtxt = sessionCtxt->getBearerContext();
899 if (bearerCtxt == NULL)
900 {
901 log_msg(LOG_DEBUG, "send_mb_req_to_sgw: bearer ctxt is NULL \n");
902 return ActStatus::HALT;
903 }
904
905 mb_msg.bearer_id = bearerCtxt->getBearerId();
906
907 memcpy(&(mb_msg.s11_sgw_c_fteid), &(sessionCtxt->getS11SgwCtrlFteid().fteid_m),
908 sizeof(struct fteid));
909
910 memcpy(&(mb_msg.s1u_enb_fteid), &(bearerCtxt->getS1uEnbUserFteid().fteid_m),
911 sizeof(struct fteid));
912
913
914 cmn::ipc::IpcAddress destAddr;
915 destAddr.u32 = TipcServiceInstance::s11AppInstanceNum_c;
916
917 mmeIpcIf_g->dispatchIpcMsg((char *) &mb_msg, sizeof(mb_msg), destAddr);
918
919 ProcedureStats::num_of_mb_req_to_sgw_sent ++;
920 log_msg(LOG_DEBUG, "Leaving send_mb_req_to_sgw \n");
921
922 return ActStatus::PROCEED;
923
924}
925
926ActStatus ActionHandlers::process_attach_cmp_from_ue(SM::ControlBlock& cb)
927{
928 log_msg(LOG_DEBUG, "Inside handle_attach_cmp_from_ue \n");
929
930 UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
931 if (ue_ctxt == NULL)
932 {
933 log_msg(LOG_ERROR, "attach_done: ue context is NULL \n");
934 return ActStatus::HALT;
935 }
936
937 ue_ctxt->setUpLnkSeqNo(ue_ctxt->getUpLnkSeqNo()+1);
938
939 ProcedureStats::num_of_processed_attach_cmp_from_ue ++;
940 log_msg(LOG_DEBUG, "Leaving handle_attach_cmp_from_ue \n");
941
942 return ActStatus::PROCEED;
943}
944
945ActStatus ActionHandlers::process_mb_resp(SM::ControlBlock& cb)
946{
947 log_msg(LOG_DEBUG, "Inside handle_mb_resp \n");
948 ProcedureStats::num_of_processed_mb_resp ++;
949 return ActStatus::PROCEED;
950}
951
952ActStatus ActionHandlers::attach_done(SM::ControlBlock& cb)
953{
954 log_msg(LOG_DEBUG, "Inside attach_done \n");
955
956 UEContext *ue_ctxt = dynamic_cast<UEContext*>(cb.getPermDataBlock());
957 if (ue_ctxt == NULL)
958 {
959 log_msg(LOG_ERROR, "attach_done: ue context is NULL \n");
960 return ActStatus::HALT;
961 }
962
963 MmContext* mmCtxt = ue_ctxt->getMmContext();
964 if (mmCtxt == NULL)
965 {
966 log_msg(LOG_ERROR, "attach_done: MMcontext is NULL \n");
967 return ActStatus::HALT;
968 }
969
970 mmCtxt->setMmState(EpsAttached);
971
972 MmeContextManagerUtils::deallocateProcedureCtxt(cb, attach_c);
973
974 ProcedureStats::num_of_attach_done++;
975 ProcedureStats::num_of_subscribers_attached ++;
976
977 log_msg(LOG_DEBUG,"Leaving attach done\n");
978
979 return ActStatus::PROCEED;
980}