Example #1
0
/****************************************************************************
 **                                                                        **
 ** Name:    _emm_attach_abnormal_cases_bcd()                          **
 **                                                                        **
 ** Description: Performs the abnormal case attach procedure.              **
 **                                                                        **
 **      3GPP TS 24.301, section 5.5.1.2.6, cases b, c and d       **
 **      The Timer T3410 shall be stopped if still running, the    **
 **      attach attempt counter shall be incremented and the UE    **
 **      shall proceed depending on whether the attach attempt     **
 **      counter reached its maximum value or not.                 **
 **                                                                        **
 ** Inputs:  None                                                      **
 **      Others:    None                                       **
 **                                                                        **
 ** Outputs:     emm_sap:   EMM service access point                   **
 **      Return:    None                                       **
 **      Others:    _emm_data, _emm_attach_data, T3402, T3410, **
 **             T3411                                      **
 **                                                                        **
 ***************************************************************************/
static void _emm_attach_abnormal_cases_bcd(emm_sap_t *emm_sap)
{
  LOG_FUNC_IN;

  LOG_TRACE(WARNING, "EMM-PROC  - Abnormal case, attach counter = %d",
            _emm_attach_data.attempt_count);

  /* Stop timer T3410 */
  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 (_emm_attach_data.attempt_count < EMM_ATTACH_COUNTER_MAX) {
    /* Increment the attach attempt counter */
    _emm_attach_data.attempt_count += 1;
    /* 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);
    /*
     * Notify EMM that the attempt to attach for EPS services failed and
     * the attach attempt counter didn't reach its maximum value; network
     * attach procedure shall be restarted when timer T3411 expires.
     */
    emm_sap->primitive = EMMREG_ATTACH_FAILED;
  } else {
    /* Delete the GUTI */
    _emm_data.guti = NULL;
    /* Delete the TAI list */
    _emm_data.ltai.n_tais = 0;
    /* Delete the last visited registered TAI */
    _emm_data.tai = NULL;
    /* Delete the list of equivalent PLMNs */
    _emm_data.nvdata.eplmn.n_plmns = 0;

    /* Delete the eKSI */
    if (_emm_data.security) {
      _emm_data.security->type = EMM_KSI_NOT_AVAILABLE;
    }

    /* Set the EPS update status to EU2 NOT UPDATED */
    _emm_data.status = EU2_NOT_UPDATED;

    /* Start T3402 timer */
    T3402.id = nas_timer_start(T3402.sec, _emm_attach_t3402_handler, NULL);
    LOG_TRACE(INFO, "EMM-PROC  - Timer T3402 (%d) expires in %ld seconds",
              T3402.id, T3402.sec);
    /*
     * Notify EMM that the attempt to attach for EPS services failed and
     * the attach attempt counter reached its maximum value.
     */
    emm_sap->primitive = EMMREG_ATTACH_EXCEEDED;
  }

  LOG_FUNC_OUT;
}
/****************************************************************************
 **                                                                        **
 ** Name:    _authentication_request()                                 **
 **                                                                        **
 ** Description: Sends AUTHENTICATION REQUEST message and start timer T3460**
 **                                                                        **
 ** Inputs:  args:      handler parameters                         **
 **      Others:    None                                       **
 **                                                                        **
 ** Outputs:     None                                                      **
 **      Return:    RETURNok, RETURNerror                      **
 **      Others:    T3460                                      **
 **                                                                        **
 ***************************************************************************/
int _authentication_request(authentication_data_t *data)
{
  LOG_FUNC_IN;

  emm_sap_t emm_sap;
  int rc;
  struct emm_data_context_s *emm_ctx;

  /*
   * Notify EMM-AS SAP that Authentication Request message has to be sent
   * to the UE
   */
  emm_sap.primitive = EMMAS_SECURITY_REQ;
  emm_sap.u.emm_as.u.security.guti = NULL;
  emm_sap.u.emm_as.u.security.ueid = data->ueid;
  emm_sap.u.emm_as.u.security.msgType = EMM_AS_MSG_TYPE_AUTH;
  emm_sap.u.emm_as.u.security.ksi = data->ksi;
  emm_sap.u.emm_as.u.security.rand = &data->rand;
  emm_sap.u.emm_as.u.security.autn = &data->autn;

  /* TODO: check for pointer validity */
#if defined(NAS_BUILT_IN_EPC)
  emm_ctx = emm_data_context_get(&_emm_data, data->ueid);
#else
  emm_ctx = _emm_data.ctx[data->ueid];
#endif

  /* Setup EPS NAS security data */
  emm_as_set_security_data(&emm_sap.u.emm_as.u.security.sctx,
                           emm_ctx->security, FALSE, TRUE);

  MSC_LOG_TX_MESSAGE(
		  MSC_NAS_EMM_MME,
		  MSC_NAS_EMM_MME,
		  NULL,0,
		  "0 EMMAS_SECURITY_REQ ue id "NAS_UE_ID_FMT" ", data->ueid);

  rc = emm_sap_send(&emm_sap);

  if (rc != RETURNerror) {
	if (emm_ctx) {
	  if (emm_ctx->T3460.id != NAS_TIMER_INACTIVE_ID) {
        /* Re-start T3460 timer */
        emm_ctx->T3460.id = nas_timer_restart(emm_ctx->T3460.id);
        MSC_LOG_EVENT(MSC_NAS_EMM_MME, "0 T3460 restarted UE "NAS_UE_ID_FMT" ", data->ueid);
      } else {
        /* Start T3460 timer */
        emm_ctx->T3460.id = nas_timer_start(emm_ctx->T3460.sec, _authentication_t3460_handler,
                                 data);
        MSC_LOG_EVENT(MSC_NAS_EMM_MME, "0 T3460 started UE "NAS_UE_ID_FMT" ", data->ueid);
      }
    }

    LOG_TRACE(INFO,"EMM-PROC  - Timer T3460 (%d) expires in %ld seconds",
    		emm_ctx->T3460.id, emm_ctx->T3460.sec);
  }

  LOG_FUNC_RETURN (rc);
}
/****************************************************************************
 **                                                                        **
 ** Name:    _identification_request()                                 **
 **                                                                        **
 ** Description: Sends IDENTITY REQUEST message and start timer T3470.     **
 **                                                                        **
 ** Inputs:  args:      handler parameters                         **
 **      Others:    None                                       **
 **                                                                        **
 ** Outputs:     None                                                      **
 **      Return:    None                                       **
 **      Others:    T3470                                      **
 **                                                                        **
 ***************************************************************************/
int _identification_request(identification_data_t *data)
{
  emm_sap_t emm_sap;
  int rc;

  struct emm_data_context_s *emm_ctx = NULL;

  LOG_FUNC_IN;

  /*
   * Notify EMM-AS SAP that Identity Request message has to be sent
   * to the UE
   */
  MSC_LOG_TX_MESSAGE(
  		MSC_NAS_EMM_MME,
  	  	MSC_NAS_EMM_MME,
  	  	NULL,0,
  	  	"0 EMMAS_SECURITY_REQ ue id "NAS_UE_ID_FMT" ", data->ueid);

  emm_sap.primitive = EMMAS_SECURITY_REQ;
  emm_sap.u.emm_as.u.security.guti = NULL;
  emm_sap.u.emm_as.u.security.ueid = data->ueid;
  emm_sap.u.emm_as.u.security.msgType = EMM_AS_MSG_TYPE_IDENT;
  emm_sap.u.emm_as.u.security.identType = data->type;

#if defined(NAS_BUILT_IN_EPC)
  if (data->ueid > 0) {
    emm_ctx = emm_data_context_get(&_emm_data, data->ueid);
  }
#else
  if (data->ueid < EMM_DATA_NB_UE_MAX) {
    emm_ctx = _emm_data.ctx[data->ueid];
  }
#endif
  /* Setup EPS NAS security data */
  emm_as_set_security_data(&emm_sap.u.emm_as.u.security.sctx,
                           emm_ctx->security, FALSE, TRUE);
  rc = emm_sap_send(&emm_sap);

  if (rc != RETURNerror) {
    if (emm_ctx->T3470.id != NAS_TIMER_INACTIVE_ID) {
      /* Re-start T3470 timer */
    	emm_ctx->T3470.id = nas_timer_restart(emm_ctx->T3470.id);
      MSC_LOG_EVENT(MSC_NAS_EMM_MME, "0 T3470 restarted UE "NAS_UE_ID_FMT" ", data->ueid);
    } else {
      /* Start T3470 timer */
      emm_ctx->T3470.id = nas_timer_start(emm_ctx->T3470.sec, _identification_t3470_handler,
                                 data);
      MSC_LOG_EVENT(MSC_NAS_EMM_MME, "0 T3470 started UE "NAS_UE_ID_FMT" ", data->ueid);
    }

    LOG_TRACE(INFO,"EMM-PROC  - Timer T3470 (%d) expires in %ld seconds",
    		emm_ctx->T3470.id, emm_ctx->T3470.sec);
  }

  LOG_FUNC_RETURN (rc);
}
Example #4
0
/****************************************************************************
 **                                                                        **
 ** Name:    esm_pt_start_timer()                                      **
 **                                                                        **
 ** Description: Start the timer of the specified procedure transaction to **
 **      expire after a given time interval. Timer expiration will **
 **      schedule execution of the callback function where stored  **
 **      ESM message should be re-transmit.                        **
 **                                                                        **
 ** Inputs:  pti:       The identity of the procedure transaction  **
 **      msg:       The encoded ESM message to be stored       **
 **      sec:       The value of the time interval in seconds  **
 **      cb:        Function executed upon timer expiration    **
 **      Others:    None                                       **
 **                                                                        **
 ** Outputs:     None                                                      **
 **      Return:    RETURNok, RETURNerror                      **
 **      Others:    _esm_pt_data                               **
 **                                                                        **
 ***************************************************************************/
int esm_pt_start_timer(int pti, const OctetString *msg,
                       long sec, nas_timer_callback_t cb)
{
  LOG_FUNC_IN;

  if ( (pti < ESM_PTI_MIN) || (pti > ESM_PTI_MAX) ) {
    LOG_FUNC_RETURN (RETURNerror);
  }

  /* Get procedure transaction data */
  esm_pt_context_t *ctx = _esm_pt_data.context[pti - ESM_PTI_MIN];

  if ( (ctx == NULL) || (ctx->pti != pti) ) {
    /* Procedure transaction not assigned */
    LOG_FUNC_RETURN (RETURNerror);
  }

  if (ctx->timer.id != NAS_TIMER_INACTIVE_ID) {
    if (ctx->args) {
      /* Re-start the retransmission timer */
      ctx->timer.id = nas_timer_restart(ctx->timer.id);
    }
  } else {
    /* Setup the retransmission timer parameters */
    ctx->args = (esm_pt_timer_data_t *)malloc(sizeof(esm_pt_timer_data_t));

    if (ctx->args) {
      /* Set the EPS bearer identity */
      ctx->args->pti = pti;
      /* Reset the retransmission counter */
      ctx->args->count = 0;
      /* Set the ESM message to be re-transmited */
      ctx->args->msg.value = (uint8_t *)malloc(msg->length);
      ctx->args->msg.length = 0;

      if (ctx->args->msg.value) {
        memcpy(ctx->args->msg.value, msg->value, msg->length);
        ctx->args->msg.length = msg->length;
      }

      /* Setup the retransmission timer to expire at the given
       * time interval */
      ctx->timer.id = nas_timer_start(sec, cb, ctx->args);
      ctx->timer.sec = sec;
    }
  }

  if ( (ctx->args != NULL) && (ctx->timer.id != NAS_TIMER_INACTIVE_ID) ) {
    LOG_TRACE(INFO, "ESM-FSM   - Retransmission timer %d expires in "
              "%ld seconds", ctx->timer.id, ctx->timer.sec);
    LOG_FUNC_RETURN (RETURNok);
  }

  LOG_FUNC_RETURN (RETURNerror);
}
/****************************************************************************
 **                                                                        **
 ** Name:    _emm_detach_t3421_handler()                               **
 **                                                                        **
 ** Description: T3421 timeout handler                                     **
 **                                                                        **
 **              3GPP TS 24.301, section 5.5.2.2.4 case c                  **
 **      On the first four expiries of the timer, the UE shall re- **
 **      transmit the DETACH REQUEST message and shall reset and   **
 **      restart timer T3421. On the fifth expiry of timer T3421,  **
 **      the detach procedure shall be aborted.                    **
 **                                                                        **
 ** Inputs:  args:      handler parameters                         **
 **      Others:    _emm_detach_data                           **
 **                                                                        **
 ** Outputs:     None                                                      **
 **      Return:    None                                       **
 **      Others:    None                                       **
 **                                                                        **
 ***************************************************************************/
void *_emm_detach_t3421_handler(void *args)
{
  LOG_FUNC_IN;

  int rc;

  /* Increment the retransmission counter */
  _emm_detach_data.count += 1;

  LOG_TRACE(WARNING, "EMM-PROC  - T3421 timer expired, "
            "retransmission counter = %d", _emm_detach_data.count);

  if (_emm_detach_data.count < EMM_DETACH_COUNTER_MAX) {
    /* Retransmit the Detach Request message */
    emm_sap_t emm_sap;
    emm_as_data_t *emm_as = &emm_sap.u.emm_as.u.data;

    /* Stop timer T3421 */
    T3421.id = nas_timer_stop(T3421.id);

    /* Setup NAS information message to transfer */
    emm_as->NASinfo = EMM_AS_NAS_INFO_DETACH;
    emm_as->NASmsg.length = 0;
    emm_as->NASmsg.value = NULL;
    /* Set the detach type */
    emm_as->type = _emm_detach_data.type;
    /* Set the switch-off indicator */
    emm_as->switch_off = _emm_detach_data.switch_off;
    /* Set the EPS mobile identity */
    emm_as->guti = _emm_data.guti;
    emm_as->ueid = 0;
    /* Setup EPS NAS security data */
    emm_as_set_security_data(&emm_as->sctx, _emm_data.security,
                             FALSE, TRUE);

    /*
     * Notify EMM-AS SAP that Detach Request message has to
     * be sent to the network
     */
    emm_sap.primitive = EMMAS_DATA_REQ;
    rc = emm_sap_send(&emm_sap);

    if (rc != RETURNerror) {
      /* Start T3421 timer */
      T3421.id = nas_timer_start(T3421.sec, _emm_detach_t3421_handler, NULL);
      LOG_TRACE(INFO, "EMM-PROC  - Timer T3421 (%d) expires in %ld "
                "seconds", T3421.id, T3421.sec);
    }
  } else {
    /* Abort the detach procedure */
    rc = _emm_detach_abort(_emm_detach_data.type);
  }

  LOG_FUNC_RETURN(NULL);
}
Example #6
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:    emm_proc_detach_request()                                 **
 **                                                                        **
 ** Description: Performs the detach procedure upon receipt of indication  **
 **      from lower layers that Detach Request message has been    **
 **      successfully delivered to the network.                    **
 **                                                                        **
 ** Inputs:  args:      Not used                                   **
 **      Others:    None                                       **
 **                                                                        **
 ** Outputs:     None                                                      **
 **      Return:    RETURNok, RETURNerror                      **
 **      Others:    T3421                                      **
 **                                                                        **
 ***************************************************************************/
int emm_proc_detach_request(void *args)
{
  LOG_FUNC_IN;

  emm_sap_t emm_sap;
  int rc;

  if ( !_emm_detach_data.switch_off ) {
    /* Start T3421 timer */
    T3421.id = nas_timer_start(T3421.sec, _emm_detach_t3421_handler, NULL);
    LOG_TRACE(INFO, "EMM-PROC  - Timer T3421 (%d) expires in %ld seconds",
              T3421.id, T3421.sec);
  }

  /*
   * Notify EMM that Detach Request has been sent to the network
   */
  emm_sap.primitive = EMMREG_DETACH_REQ;
  rc = emm_sap_send(&emm_sap);

  LOG_FUNC_RETURN(rc);
}
Example #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);
}