LowerLayer.c 21.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.0  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */

gauthier's avatar
 
gauthier committed
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
/*****************************************************************************
Source      LowerLayer.c

Version     0.1

Date        2012/03/14

Product     NAS stack

Subsystem   EPS Mobility Management

Author      Frederic Maurel

Description Defines EMM procedures executed by the Non-Access Stratum
        upon receiving notifications from lower layers so that data
        transfer succeed or failed, or NAS signalling connection is
        released, or ESM unit data has been received from under layer,
        and to request ESM unit data transfer to under layer.

*****************************************************************************/

#include "LowerLayer.h"
#include "commonDef.h"
#include "nas_log.h"

#include "emmData.h"

#include "emm_sap.h"
#include "esm_sap.h"
#include "nas_log.h"

#include <string.h> // memset

/****************************************************************************/
/****************  E X T E R N A L    D E F I N I T I O N S  ****************/
/****************************************************************************/

/****************************************************************************/
/*******************  L O C A L    D E F I N I T I O N S  *******************/
/****************************************************************************/

/****************************************************************************/
/******************  E X P O R T E D    F U N C T I O N S  ******************/
/****************************************************************************/

/*
 * --------------------------------------------------------------------------
 *          Lower layer notification handlers
 * --------------------------------------------------------------------------
 */

/****************************************************************************
 **                                                                        **
 ** Name:    lowerlayer_success()                                      **
 **                                                                        **
 ** Description: Notify the EPS Mobility Management entity that data have  **
 **      been successfully delivered to the network                **
 **                                                                        **
 **      Others:    None                                       **
 **                                                                        **
 ** Outputs:     None                                                      **
 **      Return:    RETURNok, RETURNerror                      **
 **      Others:    None                                       **
 **                                                                        **
 ***************************************************************************/
87
int lowerlayer_success(nas_user_t *user)
gauthier's avatar
 
gauthier committed
88 89 90 91 92 93 94
{
  LOG_FUNC_IN;

  emm_sap_t emm_sap;
  int rc;

  emm_sap.primitive = EMMREG_LOWERLAYER_SUCCESS;
95
  emm_sap.u.emm_reg.ueid = user->ueid;
96
  rc = emm_sap_send(user, &emm_sap);
gauthier's avatar
 
gauthier committed
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114

  LOG_FUNC_RETURN (rc);
}

/****************************************************************************
 **                                                                        **
 ** Name:    lowerlayer_failure()                                      **
 **                                                                        **
 ** Description: Notify the EPS Mobility Management entity that lower la-  **
 **      yers failed to deliver data to the network                **
 **                                                                        **
 **      Others:    None                                       **
 **                                                                        **
 ** Outputs:     None                                                      **
 **      Return:    RETURNok, RETURNerror                      **
 **      Others:    None                                       **
 **                                                                        **
 ***************************************************************************/
115
int lowerlayer_failure(nas_user_t *user)
gauthier's avatar
 
gauthier committed
116 117 118 119 120 121 122
{
  LOG_FUNC_IN;

  emm_sap_t emm_sap;
  int rc;

  emm_sap.primitive = EMMREG_LOWERLAYER_FAILURE;
123
  emm_sap.u.emm_reg.ueid = user->ueid;
124
  rc = emm_sap_send(user, &emm_sap);
gauthier's avatar
 
gauthier committed
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144

  LOG_FUNC_RETURN (rc);
}

/****************************************************************************
 **                                                                        **
 ** Name:    lowerlayer_establish()                                    **
 **                                                                        **
 ** Description: Update the EPS connection management status upon recei-   **
 **      ving indication so that the NAS signalling connection is  **
 **      established                                               **
 **                                                                        **
 ** Inputs:  None                                                      **
 **      Others:    None                                       **
 **                                                                        **
 ** Outputs:     None                                                      **
 **      Return:    RETURNok, RETURNerror                      **
 **      Others:    None                                       **
 **                                                                        **
 ***************************************************************************/
145
int lowerlayer_establish(nas_user_t *user)
gauthier's avatar
 
gauthier committed
146 147 148 149
{
  LOG_FUNC_IN;

  /* Update the EPS Connection Management status */
150
  user->emm_data->ecm_status = ECM_CONNECTED;
gauthier's avatar
 
gauthier committed
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169

  LOG_FUNC_RETURN (RETURNok);
}

/****************************************************************************
 **                                                                        **
 ** Name:    lowerlayer_release()                                      **
 **                                                                        **
 ** Description: Notify the EPS Mobility Management entity that NAS signal-**
 **      ling connection has been released                         **
 **                                                                        **
 ** Inputs:  cause:     Release cause                              **
 **      Others:    None                                       **
 **                                                                        **
 ** Outputs:     None                                                      **
 **      Return:    RETURNok, RETURNerror                      **
 **      Others:    None                                       **
 **                                                                        **
 ***************************************************************************/
170
int lowerlayer_release(nas_user_t *user, int cause)
gauthier's avatar
 
gauthier committed
171 172 173 174 175 176 177
{
  LOG_FUNC_IN;

  emm_sap_t emm_sap;
  int rc;

  /* Update the EPS Connection Management status */
178
  user->emm_data->ecm_status = ECM_IDLE;
gauthier's avatar
 
gauthier committed
179 180

  emm_sap.primitive = EMMREG_LOWERLAYER_RELEASE;
181
  emm_sap.u.emm_reg.ueid = user->ueid;
182
  rc = emm_sap_send(user, &emm_sap);
gauthier's avatar
 
gauthier committed
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201

  LOG_FUNC_RETURN (rc);
}

/****************************************************************************
 **                                                                        **
 ** Name:    lowerlayer_data_ind()                                     **
 **                                                                        **
 ** Description: Notify the EPS Session Management entity that data have   **
 **      been received from lower layers                           **
 **                                                                        **
 **      data:      Data transfered from lower layers          **
 **      Others:    None                                       **
 **                                                                        **
 ** Outputs:     None                                                      **
 **      Return:    RETURNok, RETURNerror                      **
 **      Others:    None                                       **
 **                                                                        **
 ***************************************************************************/
202
int lowerlayer_data_ind(nas_user_t *user, const OctetString *data)
gauthier's avatar
 
gauthier committed
203 204 205 206 207 208 209 210 211
{
  esm_sap_t esm_sap;
  int rc;


  LOG_FUNC_IN;

  esm_sap.primitive = ESM_UNITDATA_IND;
  esm_sap.is_standalone = TRUE;
212
  esm_sap.ueid = user->ueid;
gauthier's avatar
 
gauthier committed
213 214

  esm_sap.recv = data;
215
  rc = esm_sap_send(user, &esm_sap);
gauthier's avatar
 
gauthier committed
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234

  LOG_FUNC_RETURN (rc);
}

/****************************************************************************
 **                                                                        **
 ** Name:    lowerlayer_data_req()                                     **
 **                                                                        **
 ** Description: Notify the EPS Mobility Management entity that data have  **
 **      to be transfered to lower layers                          **
 **                                                                        **
 **          data:      Data to be transfered to lower layers      **
 **      Others:    None                                       **
 **                                                                        **
 ** Outputs:     None                                                      **
 **      Return:    RETURNok, RETURNerror                      **
 **      Others:    None                                       **
 **                                                                        **
 ***************************************************************************/
235
int lowerlayer_data_req(nas_user_t *user, const OctetString *data)
gauthier's avatar
 
gauthier committed
236 237 238 239 240 241
{
  LOG_FUNC_IN;

  int rc;
  emm_sap_t emm_sap;
  emm_security_context_t    *sctx = NULL;
242
  //struct emm_data_context_s *ctx  = NULL;
gauthier's avatar
 
gauthier committed
243 244

  emm_sap.primitive = EMMAS_DATA_REQ;
245
  emm_sap.u.emm_as.u.data.guti = user->emm_data->guti;
246
  emm_sap.u.emm_as.u.data.ueid = user->ueid;
247
  sctx = user->emm_data->security;
gauthier's avatar
 
gauthier committed
248 249 250 251 252 253

  emm_sap.u.emm_as.u.data.NASinfo = 0;
  emm_sap.u.emm_as.u.data.NASmsg.length = data->length;
  emm_sap.u.emm_as.u.data.NASmsg.value = data->value;
  /* Setup EPS NAS security data */
  emm_as_set_security_data(&emm_sap.u.emm_as.u.data.sctx, sctx, FALSE, TRUE);
254
  rc = emm_sap_send(user, &emm_sap);
gauthier's avatar
 
gauthier committed
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284

  LOG_FUNC_RETURN (rc);
}

/*
 * --------------------------------------------------------------------------
 *              EMM procedure handlers
 * --------------------------------------------------------------------------
 */
/****************************************************************************
 **                                                                        **
 ** Name:    emm_proc_lowerlayer_initialize()                          **
 **                                                                        **
 ** Description: Initialize EMM procedure handler                          **
 **                                                                        **
 ** Inputs:  success:   EMM procedure executed when data have been **
 **             successfully delivered by lower layers     **
 **      failure:   EMM procedure executed upon transmission   **
 **             failure reported by lower layers           **
 **      release:   EMM procedure executed when lower layers   **
 **             report that NAS signalling connection has  **
 **             been released                              **
 **      args:      EMM procedure argument parameters          **
 **      Others:    None                                       **
 **                                                                        **
 ** Outputs:     None                                                      **
 **      Return:    RETURNok, RETURNerror                      **
 **      Others:    _lowerlayer_data                           **
 **                                                                        **
 ***************************************************************************/
285
int emm_proc_lowerlayer_initialize(lowerlayer_data_t *lowerlayer_data, lowerlayer_success_callback_t success,
gauthier's avatar
 
gauthier committed
286 287 288 289 290 291
                                   lowerlayer_failure_callback_t failure,
                                   lowerlayer_release_callback_t release,
                                   void *args)
{
  LOG_FUNC_IN;

292 293 294 295
  lowerlayer_data->success = success;
  lowerlayer_data->failure = failure;
  lowerlayer_data->release = release;
  lowerlayer_data->args = args;
gauthier's avatar
 
gauthier committed
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315

  LOG_FUNC_RETURN (RETURNok);
}

/****************************************************************************
 **                                                                        **
 ** Name:    emm_proc_lowerlayer_success()                             **
 **                                                                        **
 ** Description: Handles EMM procedure to be executed upon receiving noti- **
 **      fication that data have been successfully delivered to    **
 **      the network.                                              **
 **                                                                        **
 ** Inputs:  None                                                      **
 **      Others:    None                                       **
 **                                                                        **
 ** Outputs:     None                                                      **
 **      Return:    RETURNok, RETURNerror                      **
 **      Others:    None                                       **
 **                                                                        **
 ***************************************************************************/
316
int emm_proc_lowerlayer_success(lowerlayer_data_t *lowerlayer_data)
gauthier's avatar
 
gauthier committed
317 318 319 320 321
{
  LOG_FUNC_IN;

  int rc = RETURNok;

322
  lowerlayer_success_callback_t emm_callback = lowerlayer_data->success;
gauthier's avatar
 
gauthier committed
323 324

  if (emm_callback) {
325 326
    rc = (*emm_callback)(lowerlayer_data->args);
    lowerlayer_data->success = NULL;
gauthier's avatar
 
gauthier committed
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347
  }

  LOG_FUNC_RETURN (rc);
}

/****************************************************************************
 **                                                                        **
 ** Name:    emm_proc_lowerlayer_failure()                             **
 **                                                                        **
 ** Description: Handles EMM procedure to be executed upon receiving noti- **
 **      fication that data failed to be delivered to the network. **
 **                                                                        **
 ** Inputs:  is_initial:    TRUE if the NAS message that failed to be  **
 **             transfered is an initial NAS message       **
 **      Others:    None                                       **
 **                                                                        **
 ** Outputs:     None                                                      **
 **      Return:    RETURNok, RETURNerror                      **
 **      Others:    None                                       **
 **                                                                        **
 ***************************************************************************/
348
int emm_proc_lowerlayer_failure(lowerlayer_data_t *lowerlayer_data, int is_initial)
gauthier's avatar
 
gauthier committed
349 350 351 352 353
{
  LOG_FUNC_IN;

  int rc = RETURNok;

354
  lowerlayer_failure_callback_t emm_callback = lowerlayer_data->failure;
gauthier's avatar
 
gauthier committed
355 356

  if (emm_callback) {
357 358
    rc = (*emm_callback)(is_initial, lowerlayer_data->args);
    lowerlayer_data->failure = NULL;
gauthier's avatar
 
gauthier committed
359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378
  }

  LOG_FUNC_RETURN (rc);
}

/****************************************************************************
 **                                                                        **
 ** Name:    emm_proc_lowerlayer_release()                             **
 **                                                                        **
 ** Description: Handles EMM procedure to be executed upon receiving noti- **
 **      fication that NAS signalling connection has been released **
 **                                                                        **
 ** Inputs:  None                                                      **
 **      Others:    None                                       **
 **                                                                        **
 ** Outputs:     None                                                      **
 **      Return:    RETURNok, RETURNerror                      **
 **      Others:    None                                       **
 **                                                                        **
 ***************************************************************************/
379
int emm_proc_lowerlayer_release(lowerlayer_data_t *lowerlayer_data)
gauthier's avatar
 
gauthier committed
380 381 382 383 384
{
  LOG_FUNC_IN;

  int rc = RETURNok;

385
  lowerlayer_release_callback_t emm_callback = lowerlayer_data->release;
gauthier's avatar
 
gauthier committed
386 387

  if (emm_callback) {
388 389
    rc = (*emm_callback)(lowerlayer_data->args);
    lowerlayer_data->release = NULL;
gauthier's avatar
 
gauthier committed
390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433
  }

  LOG_FUNC_RETURN (rc);
}

/****************************************************************************
 **                                                                        **
 ** Name:    emm_as_set_security_data()                                    **
 **                                                                        **
 ** Description: Setup security data according to the given EPS security   **
 **      context when data transfer to lower layers is requested   **
 **                                                                        **
 ** Inputs:  args:      EPS security context currently in use      **
 **      is_new:    Indicates whether a new security context   **
 **             has just been taken into use               **
 **      is_ciphered:   Indicates whether the NAS message has to   **
 **             be sent ciphered                           **
 **      Others:    None                                       **
 **                                                                        **
 ** Outputs:     data:      EPS NAS security data to be setup          **
 **      Return:    None                                       **
 **      Others:    None                                       **
 **                                                                        **
 ***************************************************************************/
void emm_as_set_security_data(emm_as_security_data_t *data, const void *args,
                              int is_new, int is_ciphered)
{
  LOG_FUNC_IN;

  const emm_security_context_t *context = (emm_security_context_t *)(args);

  memset(data, 0, sizeof(emm_as_security_data_t));

  if ( context && (context->type != EMM_KSI_NOT_AVAILABLE) ) {
    /* 3GPP TS 24.301, sections 5.4.3.3 and 5.4.3.4
     * Once a valid EPS security context exists and has been taken
     * into use, UE and MME shall cipher and integrity protect all
     * NAS signalling messages with the selected NAS ciphering and
     * NAS integrity algorithms */
    LOG_TRACE(INFO,
              "EPS security context exists is new %u KSI %u SQN %u count %u",
              is_new,
              context->eksi,
              context->ul_count.seq_num,
434
              *(uint32_t *)(&context->ul_count));
gauthier's avatar
 
gauthier committed
435 436 437 438 439 440 441 442 443 444
    LOG_TRACE(INFO,
              "knas_int %s",dump_octet_string(&context->knas_int));
    LOG_TRACE(INFO,
              "knas_enc %s",dump_octet_string(&context->knas_enc));
    LOG_TRACE(INFO,
              "kasme %s",dump_octet_string(&context->kasme));

    data->is_new = is_new;
    data->ksi    = context->eksi;
    data->sqn    = context->ul_count.seq_num;
445
    // LG data->count = *(uint32_t *)(&context->ul_count);
gauthier's avatar
 
gauthier committed
446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476
    data->count  = 0x00000000 | (context->ul_count.overflow << 8 ) | context->ul_count.seq_num;
    /* NAS integrity and cyphering keys may not be available if the
     * current security context is a partial EPS security context
     * and not a full native EPS security context */
    data->k_int = &context->knas_int;

    if (is_ciphered) {
      /* 3GPP TS 24.301, sections 4.4.5
       * When the UE establishes a new NAS signalling connection,
       * it shall send initial NAS messages integrity protected
       * and unciphered */
      /* 3GPP TS 24.301, section 5.4.3.2
       * The MME shall send the SECURITY MODE COMMAND message integrity
       * protected and unciphered */
      LOG_TRACE(WARNING,
                "EPS security context exists knas_enc");
      data->k_enc = &context->knas_enc;
    }
  } else {
    LOG_TRACE(WARNING, "EMM_AS_NO_KEY_AVAILABLE");
    /* No valid EPS security context exists */
    data->ksi = EMM_AS_NO_KEY_AVAILABLE;
  }

  LOG_FUNC_OUT;
}

/****************************************************************************/
/*********************  L O C A L    F U N C T I O N S  *********************/
/****************************************************************************/