/****************************************************************************
 **                                                                        **
 ** 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);
}
Beispiel #3
0
/****************************************************************************
 **                                                                        **
 ** 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);
}
Beispiel #5
0
/****************************************************************************
 **                                                                        **
 ** 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);
}
Beispiel #6
0
/****************************************************************************
 **                                                                        **
 ** 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);
}
Beispiel #7
0
/****************************************************************************
 **                                                                        **
 ** 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);
}
Beispiel #8
0
/****************************************************************************
 **                                                                        **
 ** 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);
}