/**************************************************************************** ** ** ** Name: emm_proc_detach_accept() ** ** ** ** Description: Performs the UE initiated detach procedure for EPS servi- ** ** ces only When the DETACH ACCEPT message is received from ** ** the network. ** ** ** ** 3GPP TS 24.301, section 5.5.2.2.2 ** ** Upon receiving the DETACH ACCEPT message, the UE shall ** ** stop timer T3421, locally deactivate all EPS bearer con- ** ** texts without peer-to-peer signalling and enter state EMM-** ** DEREGISTERED. ** ** ** ** Inputs: None ** ** Others: None ** ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** ** Others: T3421 ** ** ** ***************************************************************************/ int emm_proc_detach_accept(void) { LOG_FUNC_IN; int rc; LOG_TRACE(INFO, "EMM-PROC - UE initiated detach procedure completion"); /* Reset EMM procedure handler */ (void) emm_proc_lowerlayer_initialize(NULL, NULL, NULL, NULL); /* Stop timer T3421 */ T3421.id = nas_timer_stop(T3421.id); /* * Notify ESM that all EPS bearer contexts have to be locally deactivated */ esm_sap_t esm_sap; esm_sap.primitive = ESM_EPS_BEARER_CONTEXT_DEACTIVATE_REQ; esm_sap.data.eps_bearer_context_deactivate.ebi = ESM_SAP_ALL_EBI; rc = esm_sap_send(&esm_sap); /* * XXX - Upon receiving notification from ESM that all EPS bearer * contexts are locally deactivated, the UE is considered as * detached from the network and is entered state EMM-DEREGISTERED */ LOG_FUNC_RETURN(rc); }
/**************************************************************************** ** ** ** Name: esm_proc_pdn_disconnect_reject() ** ** ** ** Description: Performs PDN disconnection procedure not accepted by the ** ** network. ** ** ** ** 3GPP TS 24.301, section 6.5.2.4 ** ** Upon receipt of the PDN DISCONNECT REJECT message, the UE ** ** shall stop timer T3492 and enter the state PROCEDURE ** ** TRANSACTION INACTIVE and abort the PDN disconnection pro- ** ** cedure. ** ** ** ** Inputs: pti: Identifies the UE requested PDN disconnec- ** ** tion procedure rejected by the network ** ** Others: None ** ** ** ** Outputs: esm_cause: Cause code returned upon ESM procedure ** ** failure ** ** Return: RETURNok, RETURNerror ** ** Others: None ** ** ** ***************************************************************************/ int esm_proc_pdn_disconnect_reject(int pti, int *esm_cause) { LOG_FUNC_IN; int rc; LOG_TRACE(WARNING, "ESM-PROC - PDN disconnection rejected by the network " "(pti=%d), ESM cause = %d", pti, *esm_cause); /* Stop T3492 timer if running */ (void) esm_pt_stop_timer(pti); /* Set the procedure transaction state to INACTIVE */ rc = esm_pt_set_status(pti, ESM_PT_INACTIVE); if (rc != RETURNok) { /* The procedure transaction was already in INACTIVE state * as the request may have already been rejected */ LOG_TRACE(WARNING, "ESM-PROC - PTI %d was already INACTIVE", pti); *esm_cause = ESM_CAUSE_MESSAGE_TYPE_NOT_COMPATIBLE; } else { /* Release the transaction identity assigned to this procedure */ rc = esm_pt_release(pti); if (rc != RETURNok) { LOG_TRACE(WARNING, "ESM-PROC - Failed to release PTI %d", pti); *esm_cause = ESM_CAUSE_REQUEST_REJECTED_UNSPECIFIED; } else if (*esm_cause != ESM_CAUSE_LAST_PDN_DISCONNECTION_NOT_ALLOWED) { /* Get the identity of the default EPS bearer context allocated to * the PDN connection entry assigned to this procedure transaction */ int ebi = _pdn_disconnect_get_default_ebi(pti); if (ebi < 0) { LOG_TRACE(ERROR, "ESM-PROC - No default EPS bearer found"); *esm_cause = ESM_CAUSE_PROTOCOL_ERROR; LOG_FUNC_RETURN (RETURNerror); } /* * Notify ESM that all EPS bearer contexts to this PDN have to be * locally deactivated */ esm_sap_t esm_sap; esm_sap.primitive = ESM_EPS_BEARER_CONTEXT_DEACTIVATE_REQ; esm_sap.is_standalone = TRUE; esm_sap.recv = NULL; esm_sap.send.length = 0; esm_sap.data.eps_bearer_context_deactivate.ebi = ebi; rc = esm_sap_send(&esm_sap); if (rc != RETURNok) { *esm_cause = ESM_CAUSE_PROTOCOL_ERROR; } } } LOG_FUNC_RETURN(rc); }
/**************************************************************************** ** ** ** Name: emm_proc_attach_failure() ** ** ** ** Description: Performs the attach procedure abnormal case upon receipt ** ** of transmission failure of Attach Request message or At- ** ** tach Complete message. ** ** ** ** 3GPP TS 24.301, section 5.5.1.2.6, cases h and i ** ** The UE shall restart the attach procedure when timer ** ** T3411 expires. ** ** ** ** Inputs: is_initial: TRUE if the NAS message that failed to be ** ** transfered is an initial NAS message (ESM ** ** message embedded within an Attach Request ** ** message) ** ** args: Not used ** ** Others: None ** ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** ** Others: T3410, T3411 ** ** ** ***************************************************************************/ int emm_proc_attach_failure(int is_initial, void *args) { LOG_FUNC_IN; int rc = RETURNok; esm_sap_t esm_sap; LOG_TRACE(WARNING, "EMM-PROC - EPS attach failure"); /* Reset EMM procedure handler */ (void) emm_proc_lowerlayer_initialize(NULL, NULL, NULL, NULL); /* Stop timer T3410 if still running */ if (T3410.id != NAS_TIMER_INACTIVE_ID) { LOG_TRACE(INFO, "EMM-PROC - Stop timer T3410 (%d)", T3410.id); T3410.id = nas_timer_stop(T3410.id); } if (is_initial) { /* * Notify ESM that the PDN CONNECTIVITY REQUEST message contained * in the ESM message container IE of the ATTACH REQUEST has failed * to be transmitted */ esm_sap.primitive = ESM_PDN_CONNECTIVITY_REJ; esm_sap.is_standalone = FALSE; esm_sap.recv = NULL; } else { /* * Notify ESM that ACTIVATE DEFAULT EPS BEARER CONTEXT REQUEST message * contained in the ESM message container IE of the ATTACH COMPLETE * has failed to be transmitted */ esm_sap.primitive = ESM_DEFAULT_EPS_BEARER_CONTEXT_ACTIVATE_REJ; esm_sap.is_standalone = FALSE; esm_sap.recv = NULL; } rc = esm_sap_send(&esm_sap); if (rc != RETURNerror) { /* Start T3411 timer */ T3411.id = nas_timer_start(T3411.sec, _emm_attach_t3411_handler, NULL); LOG_TRACE(INFO, "EMM-PROC - Timer T3411 (%d) expires in %ld seconds", T3411.id, T3411.sec); } LOG_FUNC_RETURN(rc); }
/**************************************************************************** ** ** ** Name: lowerlayer_data_ind() ** ** ** ** Description: Notify the EPS Session Management entity that data have ** ** been received from lower layers ** ** ** ** Inputs: ueid: UE lower layer identifier ** ** data: Data transfered from lower layers ** ** Others: None ** ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** ** Others: None ** ** ** ***************************************************************************/ int lowerlayer_data_ind(unsigned int ueid, const OctetString *data) { esm_sap_t esm_sap; int rc; LOG_FUNC_IN; esm_sap.primitive = ESM_UNITDATA_IND; esm_sap.is_standalone = TRUE; esm_sap.ueid = ueid; esm_sap.recv = data; rc = esm_sap_send(&esm_sap); LOG_FUNC_RETURN (rc); }
/**************************************************************************** ** ** ** Name: emm_proc_attach_complete() ** ** ** ** Description: Terminates the attach procedure when Attach Complete mes- ** ** sage has been successfully delivered to the MME. ** ** ** ** 3GPP TS 24.301, section 5.5.1.2.4 ** ** Upon successfully sending the ATTACH COMPLETE message, ** ** the UE shall reset the attach attempt counter and tra- ** ** cking area updating attempt counter, enter state EMM- ** ** REGISTERED and set the EPS update status to EU1-UPDATED. ** ** ** ** Inputs: args: Not used ** ** Others: None ** ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** ** Others: _emm_data, _emm_attach_data ** ** ** ***************************************************************************/ int emm_proc_attach_complete(void *args) { LOG_FUNC_IN; emm_sap_t emm_sap; esm_sap_t esm_sap; int rc; LOG_TRACE(INFO, "EMM-PROC - EPS attach complete"); /* Reset EMM procedure handler */ (void) emm_proc_lowerlayer_initialize(NULL, NULL, NULL, NULL); /* Reset the attach attempt counter */ _emm_attach_data.attempt_count = 0; /* TODO: Reset the tracking area updating attempt counter */ /* Set the EPS update status to EU1 UPDATED */ _emm_data.status = EU1_UPDATED; _emm_data.is_attached = TRUE; /* * Notify EMM that network attach complete message has been delivered * to the network */ emm_sap.primitive = EMMREG_ATTACH_CNF; rc = emm_sap_send(&emm_sap); if (rc != RETURNerror) { /* * Notify ESM that the Activate Default EPS Bearer Context Accept * message has been delivered to the network within the Attach * Complete message */ esm_sap.primitive = ESM_DEFAULT_EPS_BEARER_CONTEXT_ACTIVATE_CNF; esm_sap.is_standalone = FALSE; rc = esm_sap_send(&esm_sap); } LOG_FUNC_RETURN(rc); }
/**************************************************************************** ** ** ** Name: emm_proc_attach_reject() ** ** ** ** Description: Performs the attach procedure rejected by the network. ** ** ** ** 3GPP TS 24.301, section 5.5.1.2.5 ** ** Upon receiving the ATTACH REJECT message, the UE shall ** ** stop timer T3410 and take actions depending on the EMM ** ** cause value received. ** ** ** ** Inputs: emm_cause: EMM cause indicating why the network re- ** ** jected the attach request ** ** esm_msg_pP: PDN connectivity reject ESM message ** ** Others: None ** ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** ** Others: _emm_data, _emm_attach_data, T3410 ** ** ** ***************************************************************************/ int emm_proc_attach_reject(int emm_cause, const OctetString *esm_msg_pP) { LOG_FUNC_IN; emm_sap_t emm_sap; int rc; LOG_TRACE(WARNING, "EMM-PROC - EPS attach rejected by the network, " "EMM cause = %d", emm_cause); /* Stop timer T3410 */ LOG_TRACE(INFO, "EMM-PROC - Stop timer T3410 (%d)", T3410.id); T3410.id = nas_timer_stop(T3410.id); /* Update the EPS update status, the GUTI, the visited registered TAI and * the eKSI */ switch (emm_cause) { case EMM_CAUSE_ILLEGAL_UE: case EMM_CAUSE_ILLEGAL_ME: case EMM_CAUSE_EPS_NOT_ALLOWED: case EMM_CAUSE_BOTH_NOT_ALLOWED: case EMM_CAUSE_PLMN_NOT_ALLOWED: case EMM_CAUSE_NOT_AUTHORIZED_IN_PLMN: case EMM_CAUSE_EPS_NOT_ALLOWED_IN_PLMN: case EMM_CAUSE_TA_NOT_ALLOWED: case EMM_CAUSE_ROAMING_NOT_ALLOWED: case EMM_CAUSE_NO_SUITABLE_CELLS: /* Set the EPS update status to EU3 ROAMING NOT ALLOWED */ _emm_data.status = EU3_ROAMING_NOT_ALLOWED; /* Delete the GUTI */ _emm_data.guti = NULL; /* Delete the last visited registered TAI */ _emm_data.tai = NULL; /* Delete the eKSI */ if (_emm_data.security) { _emm_data.security->type = EMM_KSI_NOT_AVAILABLE; } break; default : break; } /* Update list of equivalents PLMNs and attach attempt counter */ switch (emm_cause) { case EMM_CAUSE_ILLEGAL_UE: case EMM_CAUSE_ILLEGAL_ME: case EMM_CAUSE_EPS_NOT_ALLOWED: case EMM_CAUSE_BOTH_NOT_ALLOWED: /* Consider the USIM as invalid for EPS services */ _emm_data.usim_is_valid = FALSE; /* Delete the list of equivalent PLMNs */ _emm_data.nvdata.eplmn.n_plmns = 0; break; case EMM_CAUSE_PLMN_NOT_ALLOWED: case EMM_CAUSE_NOT_AUTHORIZED_IN_PLMN: case EMM_CAUSE_ROAMING_NOT_ALLOWED: /* Delete the list of equivalent PLMNs */ _emm_data.nvdata.eplmn.n_plmns = 0; /* Reset the attach attempt counter */ _emm_attach_data.attempt_count = 0; break; case EMM_CAUSE_TA_NOT_ALLOWED: case EMM_CAUSE_EPS_NOT_ALLOWED_IN_PLMN: case EMM_CAUSE_NO_SUITABLE_CELLS: /* Reset the attach attempt counter */ _emm_attach_data.attempt_count = 0; break; case EMM_CAUSE_ESM_FAILURE: /* 3GPP TS 24.301, section 5.5.1.2.6, case d */ if (_emm_data.NAS_SignallingPriority != 1) { /* The UE is not configured for NAS signalling low priority; * set the attach attempt counter to 5 */ _emm_attach_data.attempt_count = EMM_ATTACH_COUNTER_MAX; } break; case EMM_CAUSE_SEMANTICALLY_INCORRECT: case EMM_CAUSE_INVALID_MANDATORY_INFO: case EMM_CAUSE_MESSAGE_TYPE_NOT_IMPLEMENTED: case EMM_CAUSE_IE_NOT_IMPLEMENTED: case EMM_CAUSE_PROTOCOL_ERROR: /* 3GPP TS 24.301, section 5.5.1.2.6, case d * Set the attach attempt counter to 5 */ _emm_attach_data.attempt_count = EMM_ATTACH_COUNTER_MAX; break; default : break; } /* Update "forbidden lists" */ switch (emm_cause) { case EMM_CAUSE_PLMN_NOT_ALLOWED: case EMM_CAUSE_NOT_AUTHORIZED_IN_PLMN: /* Store the PLMN identity in the "forbidden PLMN list" */ _emm_data.fplmn.plmn[_emm_data.fplmn.n_plmns++] = _emm_data.splmn; break; case EMM_CAUSE_TA_NOT_ALLOWED: /* Store the current TAI in the list of "forbidden tracking * areas for regional provision of service" */ _emm_data.ftai.tai[_emm_data.ftai.n_tais++] = *_emm_data.tai; break; case EMM_CAUSE_ROAMING_NOT_ALLOWED: /* Store the current TAI in the list of "forbidden tracking * areas for roaming" */ _emm_data.ftai_roaming.tai[_emm_data.ftai_roaming.n_tais++] = *_emm_data.tai; break; case EMM_CAUSE_EPS_NOT_ALLOWED_IN_PLMN: /* Store the PLMN identity in the "forbidden PLMNs for GPRS * service" list */ _emm_data.fplmn_gprs.plmn[_emm_data.fplmn_gprs.n_plmns++] = _emm_data.splmn; break; default : break; } /* Update state of EMM sublayer */ switch (emm_cause) { case EMM_CAUSE_ILLEGAL_UE: case EMM_CAUSE_ILLEGAL_ME: case EMM_CAUSE_EPS_NOT_ALLOWED: case EMM_CAUSE_BOTH_NOT_ALLOWED: /* * Notify EMM that EPS attach is rejected */ emm_sap.primitive = EMMREG_ATTACH_REJ; break; case EMM_CAUSE_PLMN_NOT_ALLOWED: case EMM_CAUSE_NOT_AUTHORIZED_IN_PLMN: case EMM_CAUSE_EPS_NOT_ALLOWED_IN_PLMN: /* * Notify EMM that the UE has to perform a PLMN selection because * it is not allowed to operate in the currently selected PLMN */ emm_sap.primitive = EMMREG_REGISTER_REQ; break; case EMM_CAUSE_TA_NOT_ALLOWED: case EMM_CAUSE_ROAMING_NOT_ALLOWED: case EMM_CAUSE_NO_SUITABLE_CELLS: /* * Notify EMM that the UE failed to register to the network for * EPS services because it is not allowed to operate in the * requested tracking area */ emm_sap.primitive = EMMREG_REGISTER_REJ; break; case EMM_CAUSE_IMEI_NOT_ACCEPTED: if (_emm_data.is_emergency) { /* * Notify EMM that the UE failed to register to the network * for emergency bearer services because "IMEI not accepted" */ emm_sap.primitive = EMMREG_NO_IMSI; break; } /* break is volontary missing */ default : /* Other values are considered as abnormal cases * 3GPP TS 24.301, section 5.5.1.2.6, case d */ _emm_attach_abnormal_cases_bcd(&emm_sap); break; } rc = emm_sap_send(&emm_sap); /* * Notify ESM that the network rejected connectivity to the PDN */ if (esm_msg_pP != NULL) { esm_sap_t esm_sap; esm_sap.primitive = ESM_PDN_CONNECTIVITY_REJ; esm_sap.is_standalone = FALSE; esm_sap.recv = esm_msg_pP; rc = esm_sap_send(&esm_sap); } LOG_FUNC_RETURN(rc); }
/**************************************************************************** ** ** ** Name: emm_proc_attach_accept() ** ** ** ** Description: Performs the attach procedure accepted by the network. ** ** ** ** 3GPP TS 24.301, section 5.5.1.2.4 ** ** Upon receiving the ATTACH ACCEPT message, the UE shall ** ** stop timer T3410 and send an ATTACH COMPLETE message to ** ** the MME. ** ** ** ** Inputs: t3412: Value of the T3412 timer in seconds ** ** t3402: Value of the T3402 timer in seconds ** ** t3423: Value of the T3423 timer in seconds ** ** n_tais: Number of tracking area identities contai- ** ** ned in the TAI list ** ** tai: The TAI list that identifies the tracking ** ** areas the UE is registered to ** ** guti: New UE's temporary identity assigned by ** ** the MME (GUTI reallocation) ** ** n_eplmns: Number of equivalent PLMNs ** ** eplmns: List of equivalent PLMNs ** ** esm_msg_pP: Activate default EPS bearer context re- ** ** quest ESM message ** ** Others: None ** ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** ** Others: _emm_data, T3412, T3402, T3423 ** ** ** ***************************************************************************/ int emm_proc_attach_accept(long t3412, long t3402, long t3423, int n_tais, tai_t *tai, GUTI_t *guti, int n_eplmns, plmn_t *eplmn, const OctetString *esm_msg_pP) { LOG_FUNC_IN; emm_sap_t emm_sap; esm_sap_t esm_sap; int rc; int i; int j; LOG_TRACE(INFO, "EMM-PROC - EPS attach accepted by the network"); /* Stop timer T3410 */ LOG_TRACE(INFO, "EMM-PROC - Stop timer T3410 (%d)", T3410.id); T3410.id = nas_timer_stop(T3410.id); /* Delete old TAI list and store the received TAI list */ _emm_data.ltai.n_tais = n_tais; for (i = 0; (i < n_tais) && (i < EMM_DATA_TAI_MAX); i++) { _emm_data.ltai.tai[i] = tai[i]; } /* Update periodic tracking area update timer value */ T3412.sec = t3412; /* Update attach failure timer value */ if ( !(t3402 < 0) ) { T3402.sec = t3402; } /* Update E-UTRAN deactivate ISR timer value */ if ( !(t3423 < 0) ) { T3423.sec = t3423; } /* Delete old GUTI and store the new assigned GUTI if provided */ if (guti) { *_emm_data.guti = *guti; } /* Update the stored list of equivalent PLMNs */ _emm_data.nvdata.eplmn.n_plmns = 0; if (n_eplmns > 0) { for (i = 0; (i < n_eplmns) && (i < EMM_DATA_EPLMN_MAX); i++) { int is_forbidden = FALSE; if (!_emm_data.is_emergency) { /* If the attach procedure is not for emergency bearer * services, the UE shall remove from the list any PLMN * code that is already in the list of forbidden PLMNs */ for (j = 0; j < _emm_data.fplmn.n_plmns; j++) { if (PLMNS_ARE_EQUAL(eplmn[i], _emm_data.fplmn.plmn[j])) { is_forbidden = TRUE; break; } } } if ( !is_forbidden ) { _emm_data.nvdata.eplmn.plmn[_emm_data.nvdata.eplmn.n_plmns++] = eplmn[i]; } } /* Add the PLMN code of the registered PLMN that sent the list */ if (_emm_data.nvdata.eplmn.n_plmns < EMM_DATA_EPLMN_MAX) { _emm_data.nvdata.eplmn.plmn[_emm_data.nvdata.eplmn.n_plmns++] = _emm_data.splmn; } } /* * Notify ESM that a default EPS bearer has to be activated */ esm_sap.primitive = ESM_DEFAULT_EPS_BEARER_CONTEXT_ACTIVATE_REQ; esm_sap.is_standalone = FALSE; esm_sap.recv = esm_msg_pP; rc = esm_sap_send(&esm_sap); if ( (rc != RETURNerror) && (esm_sap.err == ESM_SAP_SUCCESS) ) { /* Setup EMM procedure handler to be executed upon receiving * lower layer notification */ rc = emm_proc_lowerlayer_initialize(emm_proc_attach_complete, emm_proc_attach_failure, NULL, NULL); if (rc != RETURNok) { LOG_TRACE(WARNING, "EMM-PROC - Failed to initialize EMM procedure handler"); LOG_FUNC_RETURN (RETURNerror); } /* * Notify EMM-AS SAP that Attach Complete message together with * an Activate Default EPS Bearer Context Accept message has to * be sent to the network */ emm_sap.primitive = EMMAS_DATA_REQ; emm_sap.u.emm_as.u.data.guti = _emm_data.guti; emm_sap.u.emm_as.u.data.ueid = 0; /* Setup EPS NAS security data */ emm_as_set_security_data(&emm_sap.u.emm_as.u.data.sctx, _emm_data.security, FALSE, TRUE); /* Get the activate default EPS bearer context accept message * to be transfered within the ESM container of the attach * complete message */ emm_sap.u.emm_as.u.data.NASinfo = EMM_AS_NAS_DATA_ATTACH; emm_sap.u.emm_as.u.data.NASmsg = esm_sap.send; rc = emm_sap_send(&emm_sap); } else if (esm_sap.err != ESM_SAP_DISCARDED) { /* 3GPP TS 24.301, section 5.5.1.2.6, case j * If the ACTIVATE DEFAULT BEARER CONTEXT REQUEST message combined * with the ATTACH ACCEPT is not accepted by the UE due to failure * in the UE ESM sublayer, then the UE shall initiate the detach * procedure by sending a DETACH REQUEST message to the network. */ emm_sap.primitive = EMMREG_DETACH_INIT; rc = emm_sap_send(&emm_sap); } else { /* * ESM procedure failed and, received message has been discarded or * Status message has been returned; ignore ESM procedure failure */ rc = RETURNok; } LOG_FUNC_RETURN(rc); }
/**************************************************************************** ** ** ** Name: emm_proc_attach() ** ** ** ** Description: Initiate EPS attach procedure to register a UE in PS mode ** ** of operation for EPS services only, or register a UE for ** ** emergency bearer services. ** ** ** ** 3GPP TS 24.301, section 5.5.1.2.2 ** ** In state EMM-DEREGISTERED, the UE initiates the attach ** ** procedure by sending an ATTACH REQUEST message to the MME,** ** starting timer T3410 and entering state EMM-REGISTERED- ** ** INITIATED. ** ** ** ** Inputs: type: Type of the requested attach ** ** Others: _emm_data ** ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** ** Others: T3402, T3410, T3411 ** ** ** ***************************************************************************/ int emm_proc_attach(emm_proc_attach_type_t type) { LOG_FUNC_IN; emm_sap_t emm_sap; emm_as_establish_t *emm_as = &emm_sap.u.emm_as.u.establish; esm_sap_t esm_sap; int rc; LOG_TRACE(INFO, "EMM-PROC - Initiate EPS attach type = %s (%d)", _emm_attach_type_str[type], type); /* Update the emergency bearer service indicator */ if (type == EMM_ATTACH_TYPE_EMERGENCY) { _emm_data.is_emergency = TRUE; } /* Setup initial NAS information message to transfer */ emm_as->NASinfo = EMM_AS_NAS_INFO_ATTACH; /* Set the attach type */ emm_as->type = type; /* Set the RRC connection establishment cause */ if (_emm_data.is_emergency) { emm_as->RRCcause = NET_ESTABLISH_CAUSE_EMERGENCY; emm_as->RRCtype = NET_ESTABLISH_TYPE_EMERGENCY_CALLS; } else { emm_as->RRCcause = NET_ESTABLISH_CAUSE_MO_SIGNAL; emm_as->RRCtype = NET_ESTABLISH_TYPE_ORIGINATING_SIGNAL; } /* Set the PLMN identifier of the selected PLMN */ emm_as->plmnID = &_emm_data.splmn; /* * Process the EPS mobile identity */ emm_as->UEid.guti = NULL; emm_as->UEid.tai = NULL; emm_as->UEid.imsi = NULL; emm_as->UEid.imei = NULL; /* Check whether the UE is configured for "AttachWithIMSI" */ if (_emm_data.AttachWithImsi) { /* Check whether the selected PLMN is neither the registered PLMN * nor in the list of equivalent PLMNs */ if ( (!_emm_data.is_rplmn) && (!_emm_data.is_eplmn) ) { LOG_TRACE(INFO, "EMM-PROC - Initiate EPS attach with IMSI"); /* Include the IMSI */ emm_as->UEid.imsi = _emm_data.imsi; } else { LOG_TRACE(INFO, "EMM-PROC - Initiate EPS attach with NO IMSI, is registered PLMN %d, is equivalent PLMN %d", _emm_data.is_rplmn, _emm_data.is_eplmn); } } else if (_emm_data.guti) { LOG_TRACE(INFO, "EMM-PROC - Initiate EPS attach with GUTI"); /* Include a valid GUTI and the last visited registered TAI */ emm_as->UEid.guti = _emm_data.guti; emm_as->UEid.tai = _emm_data.tai; } else if (!_emm_data.is_emergency) { LOG_TRACE(INFO, "EMM-PROC - Initiate EPS attach with IMSI cause is no emergency and no GUTI"); /* Include the IMSI if no valid GUTI is available */ emm_as->UEid.imsi = _emm_data.imsi; } else { /* The UE is attaching for emergency bearer services and * does not hold a valid GUTI */ if (_emm_data.imsi) { /* Include the IMSI if valid (USIM is present) */ LOG_TRACE(INFO, "EMM-PROC - Initiate EPS attach with IMSI cause is emergency and no GUTI"); emm_as->UEid.imsi = _emm_data.imsi; } else { LOG_TRACE(INFO, "EMM-PROC - Initiate EPS attach with IMSI cause is emergency and no GUTI and no IMSI"); /* Include the IMEI if the IMSI is not valid */ emm_as->UEid.imei = _emm_data.imei; } } /* Setup EPS NAS security data */ emm_as_set_security_data(&emm_as->sctx, _emm_data.security, FALSE, FALSE); emm_as->ksi = EMM_AS_NO_KEY_AVAILABLE; if (_emm_data.security) { if (_emm_data.security->type != EMM_KSI_NOT_AVAILABLE) { emm_as->ksi = _emm_data.security->eksi; } LOG_TRACE(INFO, "EMM-PROC - eps_encryption 0x%X", _emm_data.security->capability.eps_encryption); LOG_TRACE(INFO, "EMM-PROC - eps_integrity 0x%X", _emm_data.security->capability.eps_integrity); emm_as->encryption = _emm_data.security->capability.eps_encryption; emm_as->integrity = _emm_data.security->capability.eps_integrity; } /* * Notify ESM that initiation of a PDN connectivity procedure * is requested to setup a default EPS bearer */ esm_sap.primitive = ESM_PDN_CONNECTIVITY_REQ; esm_sap.is_standalone = FALSE; esm_sap.data.pdn_connect.is_defined = TRUE; esm_sap.data.pdn_connect.cid = 1; /* TODO: PDN type should be set according to the IP capability of the UE */ esm_sap.data.pdn_connect.pdn_type = NET_PDN_TYPE_IPV4V6; esm_sap.data.pdn_connect.apn = NULL; esm_sap.data.pdn_connect.is_emergency = _emm_data.is_emergency; rc = esm_sap_send(&esm_sap); if (rc != RETURNerror) { /* Setup EMM procedure handler to be executed upon receiving * lower layer notification */ rc = emm_proc_lowerlayer_initialize(emm_proc_attach_request, emm_proc_attach_failure, emm_proc_attach_release, NULL); if (rc != RETURNok) { LOG_TRACE(WARNING, "Failed to initialize EMM procedure handler"); LOG_FUNC_RETURN (RETURNerror); } /* Start T3410 timer */ T3410.id = nas_timer_start(T3410.sec, _emm_attach_t3410_handler, NULL); LOG_TRACE(INFO,"EMM-PROC - Timer T3410 (%d) expires in %ld seconds", T3410.id, T3410.sec); /* Stop T3402 and T3411 timers if running */ T3402.id = nas_timer_stop(T3402.id); T3411.id = nas_timer_stop(T3411.id); /* * Notify EMM-AS SAP that a RRC connection establishment procedure * is requested from the Access-Stratum to send initial NAS message * attach request to the network */ emm_sap.primitive = EMMAS_ESTABLISH_REQ; /* Get the PDN connectivity request to transfer within the ESM * container of the initial attach request message */ emm_sap.u.emm_as.u.establish.NASmsg = esm_sap.send; rc = emm_sap_send(&emm_sap); } LOG_FUNC_RETURN(rc); }
/**************************************************************************** ** ** ** Name: _pdn_disconnect_t3492_handler() ** ** ** ** Description: T3492 timeout handler ** ** ** ** 3GPP TS 24.301, section 6.5.2.5, case a ** ** On the first expiry of the timer T3492, the UE shall re- ** ** send the PDN DISCONNECT REQUEST and shall reset and re- ** ** start timer T3492. This retransmission is repeated four ** ** times, i.e. on the fifth expiry of timer T3492, the UE ** ** shall abort the procedure, deactivate all EPS bearer con- ** ** texts for this PDN connection locally, release the PTI ** ** allocated for this invocation and enter the state PROCE- ** ** DURE TRANSACTION INACTIVE. ** ** ** ** Inputs: args: handler parameters ** ** Others: None ** ** ** ** Outputs: None ** ** Return: None ** ** Others: None ** ** ** ***************************************************************************/ static void *_pdn_disconnect_t3492_handler(void *args) { LOG_FUNC_IN; int rc; /* Get retransmission timer parameters data */ esm_pt_timer_data_t *data = (esm_pt_timer_data_t *)(args); /* Increment the retransmission counter */ data->count += 1; LOG_TRACE(WARNING, "ESM-PROC - T3492 timer expired (pti=%d), " "retransmission counter = %d", data->pti, data->count); if (data->count < ESM_PDN_DISCONNECT_COUNTER_MAX) { emm_sap_t emm_sap; emm_esm_data_t *emm_esm = &emm_sap.u.emm_esm.u.data; /* * Notify EMM that the PDN connectivity request message * has to be sent again */ emm_sap.primitive = EMMESM_UNITDATA_REQ; emm_sap.u.emm_esm.ueid = 0; emm_esm->msg.length = data->msg.length; emm_esm->msg.value = data->msg.value; rc = emm_sap_send(&emm_sap); if (rc != RETURNerror) { /* Restart the timer T3492 */ rc = esm_pt_start_timer(data->pti, &data->msg, T3492_DEFAULT_VALUE, _pdn_disconnect_t3492_handler); } } else { /* Set the procedure transaction state to INACTIVE */ rc = esm_pt_set_status(data->pti, ESM_PT_INACTIVE); if (rc != RETURNok) { /* The procedure transaction was already in INACTIVE state */ LOG_TRACE(WARNING, "ESM-PROC - PTI %d was already INACTIVE", data->pti); } else { /* Release the transaction identity assigned to this procedure */ rc = esm_pt_release(data->pti); if (rc != RETURNok) { LOG_TRACE(WARNING, "ESM-PROC - Failed to release PTI %d", data->pti); } else { /* Get the identity of the default EPS bearer context * allocated to the PDN connection entry assigned to * this procedure transaction */ int ebi = _pdn_disconnect_get_default_ebi(data->pti); if (ebi < 0) { LOG_TRACE(ERROR, "ESM-PROC - No default EPS bearer found"); LOG_FUNC_RETURN (NULL); } /* * Notify ESM that all EPS bearer contexts to this PDN have * to be locally deactivated */ esm_sap_t esm_sap; esm_sap.primitive = ESM_EPS_BEARER_CONTEXT_DEACTIVATE_REQ; esm_sap.is_standalone = TRUE; esm_sap.recv = NULL; esm_sap.send.length = 0; esm_sap.data.eps_bearer_context_deactivate.ebi = ebi; rc = esm_sap_send(&esm_sap); } } } LOG_FUNC_RETURN(NULL); }
/**************************************************************************** ** ** ** Name: esm_proc_eps_bearer_context_deactivate_request() ** ** ** ** Description: Deletes the EPS bearer context identified by the EPS bea- ** ** rer identity upon receipt of the DEACTIVATE EPS BEARER ** ** CONTEXT REQUEST message. ** ** ** ** Inputs: ebi: EPS bearer identity ** ** Others: None ** ** ** ** Outputs: esm_cause: Cause code returned upon ESM procedure ** ** failure ** ** Return: RETURNok, RETURNerror ** ** Others: None ** ** ** ***************************************************************************/ int esm_proc_eps_bearer_context_deactivate_request(int ebi, int *esm_cause) { LOG_FUNC_IN; int pid, bid; int rc = RETURNok; LOG_TRACE(INFO, "ESM-PROC - EPS bearer context deactivation " "requested by the network (ebi=%d)", ebi); /* Release the EPS bearer context entry */ if (esm_ebr_context_release(ebi, &pid, &bid) == ESM_EBI_UNASSIGNED) { LOG_TRACE(WARNING, "ESM-PROC - Failed to release EPS bearer context"); *esm_cause = ESM_CAUSE_PROTOCOL_ERROR; LOG_FUNC_RETURN (RETURNerror); } if (bid == 0) { /* The EPS bearer identity is that of the default bearer assigned to * the PDN connection */ if (*esm_cause == ESM_CAUSE_REACTIVATION_REQUESTED) { esm_sap_t esm_sap; int active = FALSE; /* 3GPP TS 24.301, section 6.4.4.3 * The UE should re-initiate the UE requested PDN connectivity * procedure for the APN associated to the PDN it was connected * to in order to reactivate the EPS bearer context */ LOG_TRACE(WARNING, "ESM-PROC - The network requests PDN " "connection reactivation"); /* Get PDN context parameters */ rc = esm_main_get_pdn(pid + 1, &esm_sap.data.pdn_connect.pdn_type, &esm_sap.data.pdn_connect.apn, &esm_sap.data.pdn_connect.is_emergency, &active); if (rc != RETURNerror) { if (active) { LOG_TRACE(ERROR, "ESM-PROC - Connectivity to APN %s " "has not been deactivated", esm_sap.data.pdn_connect.apn); *esm_cause = ESM_CAUSE_REQUEST_REJECTED_UNSPECIFIED; LOG_FUNC_RETURN (RETURNerror); } /* * Notify ESM to re-initiate PDN connectivity procedure */ esm_sap.primitive = ESM_PDN_CONNECTIVITY_REQ; esm_sap.is_standalone = TRUE; esm_sap.data.pdn_connect.is_defined = TRUE; esm_sap.data.pdn_connect.cid = pid + 1; rc = esm_sap_send(&esm_sap); } } } LOG_FUNC_RETURN (rc); }