EmmCommon.c 20 KB
Newer Older
Lionel Gauthier's avatar
GPLv3  
Lionel Gauthier committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/*******************************************************************************
    OpenAirInterface
    Copyright(c) 1999 - 2014 Eurecom

    OpenAirInterface is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.


    OpenAirInterface is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
Cedric Roux's avatar
 
Cedric Roux committed
15

Lionel Gauthier's avatar
GPLv3  
Lionel Gauthier committed
16 17 18 19 20 21 22 23 24 25 26 27 28 29
    You should have received a copy of the GNU General Public License
    along with OpenAirInterface.The full GNU General Public License is
   included in this distribution in the file called "COPYING". If not,
   see <http://www.gnu.org/licenses/>.

  Contact Information
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
  OpenAirInterface Dev  : openair4g-devel@eurecom.fr

  Address      : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.

 *******************************************************************************/
/*****************************************************************************
Cedric Roux's avatar
Cedric Roux committed
30
Source      EmmCommon.h
Cedric Roux's avatar
 
Cedric Roux committed
31

Cedric Roux's avatar
Cedric Roux committed
32
Version     0.1
Cedric Roux's avatar
 
Cedric Roux committed
33

Cedric Roux's avatar
Cedric Roux committed
34
Date        2013/04/19
Cedric Roux's avatar
 
Cedric Roux committed
35

Cedric Roux's avatar
Cedric Roux committed
36
Product     NAS stack
Cedric Roux's avatar
 
Cedric Roux committed
37

Cedric Roux's avatar
Cedric Roux committed
38
Subsystem   EPS Mobility Management
Cedric Roux's avatar
 
Cedric Roux committed
39

Cedric Roux's avatar
Cedric Roux committed
40
Author      Frederic Maurel
Cedric Roux's avatar
 
Cedric Roux committed
41

Cedric Roux's avatar
Cedric Roux committed
42 43
Description Defines callback functions executed within EMM common procedures
        by the Non-Access Stratum running at the network side.
Cedric Roux's avatar
 
Cedric Roux committed
44

Cedric Roux's avatar
Cedric Roux committed
45 46
        Following EMM common procedures can always be initiated by the
        network whilst a NAS signalling connection exists:
Cedric Roux's avatar
 
Cedric Roux committed
47

Cedric Roux's avatar
Cedric Roux committed
48 49 50 51 52
        GUTI reallocation
        authentication
        security mode control
        identification
        EMM information
Cedric Roux's avatar
 
Cedric Roux committed
53 54 55 56 57 58 59 60 61 62 63

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

#ifdef NAS_MME

#include "EmmCommon.h"

#include "commonDef.h"
#include "nas_log.h"
#include "emmData.h"

Cedric Roux's avatar
Cedric Roux committed
64
#include <stdlib.h> // malloc, free
Cedric Roux's avatar
 
Cedric Roux committed
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
#include <string.h>
#include <assert.h>

#if defined(EPC_BUILD)
# include "assertions.h"
#endif

/****************************************************************************/
/****************  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  *******************/
/****************************************************************************/

Cedric Roux's avatar
Cedric Roux committed
80
/* EMM procedure callback cleanup function  */
Cedric Roux's avatar
 
Cedric Roux committed
81 82
static void _emm_common_cleanup(unsigned int ueid);

Cedric Roux's avatar
Cedric Roux committed
83
/* Ongoing EMM procedure callback functions */
Cedric Roux's avatar
 
Cedric Roux committed
84 85 86 87 88 89 90
typedef struct emm_common_data_s {
    unsigned int ueid;
    int ref_count;
    emm_common_success_callback_t success;
    emm_common_reject_callback_t  reject;
    emm_common_failure_callback_t failure;
    emm_common_abort_callback_t   abort;
Cedric Roux's avatar
Cedric Roux committed
91
    void *args;
Cedric Roux's avatar
 
Cedric Roux committed
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144

#if defined(EPC_BUILD)
    RB_ENTRY(emm_common_data_s) entries;
#endif
} emm_common_data_t;

#if defined(EPC_BUILD)
typedef struct emm_common_data_head_s {
    RB_HEAD(emm_common_data_map, emm_common_data_s) emm_common_data_root;
} emm_common_data_head_t;

emm_common_data_head_t emm_common_data_head = { RB_INITIALIZER() };

static inline
int emm_common_data_compare_ueid(struct emm_common_data_s *p1,
                                 struct emm_common_data_s *p2);
struct emm_common_data_s *emm_common_data_context_get(
    struct emm_common_data_head_s *root, unsigned int _ueid);

RB_PROTOTYPE(emm_common_data_map, emm_common_data_s, entries,
             emm_common_data_compare_ueid);

/* Generate functions used for the MAP */
RB_GENERATE(emm_common_data_map, emm_common_data_s, entries,
            emm_common_data_compare_ueid);

static inline
int emm_common_data_compare_ueid(struct emm_common_data_s *p1,
                                 struct emm_common_data_s *p2)
{
    if (p1->ueid > p2->ueid) {
        return 1;
    }
    if (p1->ueid < p2->ueid) {
        return -1;
    }
    /* Matching reference -> return 0 */
    return 0;
}

struct emm_common_data_s *emm_common_data_context_get(
    struct emm_common_data_head_s *root, unsigned int _ueid)
{
    struct emm_common_data_s reference;

    DevAssert(root != NULL);
    DevCheck(_ueid > 0, _ueid, 0, 0);

    memset(&reference, 0, sizeof(struct emm_common_data_s));
    reference.ueid = _ueid;
    return RB_FIND(emm_common_data_map, &root->emm_common_data_root, &reference);
}
#else
Cedric Roux's avatar
Cedric Roux committed
145
static emm_common_data_t *_emm_common_data[EMM_DATA_NB_UE_MAX];
Cedric Roux's avatar
 
Cedric Roux committed
146 147 148 149 150 151 152 153
#endif

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

/****************************************************************************
 **                                                                        **
Cedric Roux's avatar
Cedric Roux committed
154
 ** Name:    emm_proc_common_initialize()                              **
Cedric Roux's avatar
 
Cedric Roux committed
155 156
 **                                                                        **
 ** Description: Initialize EMM procedure callback functions executed for  **
Cedric Roux's avatar
Cedric Roux committed
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
 **      the UE with the given identifier                          **
 **                                                                        **
 ** Inputs:  ueid:      UE lower layer identifier                  **
 **      success:   EMM procedure executed upon successful EMM **
 **             common procedure completion                **
 **      reject:    EMM procedure executed if the EMM common   **
 **             procedure failed or is rejected            **
 **      failure:   EMM procedure executed upon transmission   **
 **             failure reported by lower layer            **
 **      abort:     EMM common procedure executed when the on- **
 **             going EMM procedure is aborted             **
 **      args:      EMM common procedure argument parameters   **
 **      Others:    None                                       **
 **                                                                        **
 ** Outputs:     None                                                      **
 **      Return:    RETURNok, RETURNerror                      **
 **      Others:    _emm_common_data                           **
Cedric Roux's avatar
 
Cedric Roux committed
174 175 176
 **                                                                        **
 ***************************************************************************/
int emm_proc_common_initialize(unsigned int ueid,
Cedric Roux's avatar
Cedric Roux committed
177 178 179 180 181
                               emm_common_success_callback_t _success,
                               emm_common_reject_callback_t  _reject,
                               emm_common_failure_callback_t _failure,
                               emm_common_abort_callback_t   _abort,
                               void *args)
Cedric Roux's avatar
 
Cedric Roux committed
182 183 184 185 186 187 188 189 190 191 192 193
{
    struct emm_common_data_s *emm_common_data_ctx = NULL;
    LOG_FUNC_IN;

#if defined(EPC_BUILD)
    assert(ueid > 0);
    emm_common_data_ctx = emm_common_data_context_get(&emm_common_data_head, ueid);
#else
    assert(ueid < EMM_DATA_NB_UE_MAX);
#endif

    if (emm_common_data_ctx == NULL) {
Cedric Roux's avatar
Cedric Roux committed
194
        emm_common_data_ctx = (emm_common_data_t *)malloc(sizeof(emm_common_data_t));
Cedric Roux's avatar
 
Cedric Roux committed
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
        emm_common_data_ctx->ueid = ueid;
#if defined(EPC_BUILD)
        RB_INSERT(emm_common_data_map, &emm_common_data_head.emm_common_data_root,
                  emm_common_data_ctx);
#endif
        if (emm_common_data_ctx) {
            emm_common_data_ctx->ref_count = 0;
        }
    }
    if (emm_common_data_ctx) {
        emm_common_data_ctx->ref_count += 1;
        emm_common_data_ctx->success = _success;
        emm_common_data_ctx->reject  = _reject;
        emm_common_data_ctx->failure = _failure;
        emm_common_data_ctx->abort   = _abort;
        emm_common_data_ctx->args    = args;
        LOG_FUNC_RETURN(RETURNok);
    }

    LOG_FUNC_RETURN(RETURNerror);
}

/****************************************************************************
 **                                                                        **
Cedric Roux's avatar
Cedric Roux committed
219
 ** Name:    emm_proc_common_success()                                 **
Cedric Roux's avatar
 
Cedric Roux committed
220 221
 **                                                                        **
 ** Description: The EMM common procedure initiated between the UE with    **
Cedric Roux's avatar
Cedric Roux committed
222 223 224
 **      the specified identifier and the MME completed success-   **
 **      fully. The network performs required actions related to   **
 **      the ongoing EMM procedure.                                **
Cedric Roux's avatar
 
Cedric Roux committed
225
 **                                                                        **
Cedric Roux's avatar
Cedric Roux committed
226 227
 ** Inputs:  ueid:      UE lower layer identifier                  **
 **      Others:    _emm_common_data, _emm_data                **
Cedric Roux's avatar
 
Cedric Roux committed
228
 **                                                                        **
Cedric Roux's avatar
Cedric Roux committed
229 230 231
 ** Outputs:     None                                                      **
 **      Return:    RETURNok, RETURNerror                      **
 **      Others:    None                                       **
Cedric Roux's avatar
 
Cedric Roux committed
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271
 **                                                                        **
 ***************************************************************************/
int emm_proc_common_success(unsigned int ueid)
{
    emm_common_data_t             *emm_common_data_ctx = NULL;
    emm_common_success_callback_t  emm_callback;

    int rc = RETURNerror;

    LOG_FUNC_IN;

#if defined(EPC_BUILD)
    DevCheck(ueid > 0, ueid, 0, 0);
    emm_common_data_ctx = emm_common_data_context_get(&emm_common_data_head, ueid);
#else
    assert(ueid < EMM_DATA_NB_UE_MAX);
    emm_common_data_ctx = _emm_common_data[ueid];
#endif

    assert(emm_common_data_ctx != NULL);

    emm_callback = emm_common_data_ctx->success;
    if (emm_callback) {
        struct emm_data_context_s *ctx = NULL;

#if defined(EPC_BUILD)
        ctx = emm_data_context_get(&_emm_data, ueid);
#else
        ctx = _emm_data.ctx[ueid];
#endif
        rc = (*emm_callback)(ctx);
    }

    _emm_common_cleanup(ueid);

    LOG_FUNC_RETURN(rc);
}

/****************************************************************************
 **                                                                        **
Cedric Roux's avatar
Cedric Roux committed
272
 ** Name:    emm_proc_common_reject()                                  **
Cedric Roux's avatar
 
Cedric Roux committed
273 274
 **                                                                        **
 ** Description: The EMM common procedure initiated between the UE with    **
Cedric Roux's avatar
Cedric Roux committed
275 276 277
 **      the specified identifier and the MME failed or has been   **
 **      rejected. The network performs required actions related   **
 **      to the ongoing EMM procedure.                             **
Cedric Roux's avatar
 
Cedric Roux committed
278
 **                                                                        **
Cedric Roux's avatar
Cedric Roux committed
279 280
 ** Inputs:  ueid:      UE lower layer identifier                  **
 **      Others:    _emm_common_data, _emm_data                **
Cedric Roux's avatar
 
Cedric Roux committed
281
 **                                                                        **
Cedric Roux's avatar
Cedric Roux committed
282 283 284
 ** Outputs:     None                                                      **
 **      Return:    RETURNok, RETURNerror                      **
 **      Others:    None                                       **
Cedric Roux's avatar
 
Cedric Roux committed
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324
 **                                                                        **
 ***************************************************************************/
int emm_proc_common_reject(unsigned int ueid)
{
    emm_common_data_t *emm_common_data_ctx = NULL;
    int rc = RETURNerror;
    emm_common_reject_callback_t emm_callback;

    LOG_FUNC_IN;

#if defined(EPC_BUILD)
    DevCheck(ueid > 0, ueid, 0, 0);
    emm_common_data_ctx = emm_common_data_context_get(&emm_common_data_head, ueid);
#else
    assert(ueid < EMM_DATA_NB_UE_MAX);
    emm_common_data_ctx = _emm_common_data[ueid];
#endif

    assert(emm_common_data_ctx != NULL);

    emm_callback = emm_common_data_ctx->reject;

    if (emm_callback) {
        struct emm_data_context_s *ctx = NULL;

#if defined(EPC_BUILD)
        ctx = emm_data_context_get(&_emm_data, ueid);
#else
        ctx = _emm_data.ctx[ueid];
#endif
        rc = (*emm_callback)(ctx);
    }

    _emm_common_cleanup(ueid);

    LOG_FUNC_RETURN(rc);
}

/****************************************************************************
 **                                                                        **
Cedric Roux's avatar
Cedric Roux committed
325
 ** Name:    emm_proc_common_failure()                                 **
Cedric Roux's avatar
 
Cedric Roux committed
326 327
 **                                                                        **
 ** Description: The EMM common procedure has been initiated between the   **
Cedric Roux's avatar
Cedric Roux committed
328 329 330 331
 **      UE with the specified identifier and the MME, and a lower **
 **      layer failure occurred before the EMM common procedure    **
 **      being completed. The network performs required actions    **
 **      related to the ongoing EMM procedure.                     **
Cedric Roux's avatar
 
Cedric Roux committed
332
 **                                                                        **
Cedric Roux's avatar
Cedric Roux committed
333 334
 ** Inputs:  ueid:      UE lower layer identifier                  **
 **      Others:    _emm_common_data, _emm_data                **
Cedric Roux's avatar
 
Cedric Roux committed
335
 **                                                                        **
Cedric Roux's avatar
Cedric Roux committed
336 337 338
 ** Outputs:     None                                                      **
 **      Return:    RETURNok, RETURNerror                      **
 **      Others:    None                                       **
Cedric Roux's avatar
 
Cedric Roux committed
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377
 **                                                                        **
 ***************************************************************************/
int emm_proc_common_failure(unsigned int ueid)
{
    emm_common_data_t             *emm_common_data_ctx = NULL;
    emm_common_failure_callback_t  emm_callback;

    int rc = RETURNerror;

    LOG_FUNC_IN;

#if defined(EPC_BUILD)
    DevCheck(ueid > 0, ueid, 0, 0);
    emm_common_data_ctx = emm_common_data_context_get(&emm_common_data_head, ueid);
#else
    assert(ueid < EMM_DATA_NB_UE_MAX);
    emm_common_data_ctx = _emm_common_data[ueid];
#endif
    assert(emm_common_data_ctx != NULL);

    emm_callback = emm_common_data_ctx->failure;
    if (emm_callback) {
        struct emm_data_context_s *ctx = NULL;

#if defined(EPC_BUILD)
        ctx = emm_data_context_get(&_emm_data, ueid);
#else
        ctx = _emm_data.ctx[ueid];
#endif
        rc = (*emm_callback)(ctx);
    }

    _emm_common_cleanup(ueid);

    LOG_FUNC_RETURN(rc);
}

/****************************************************************************
 **                                                                        **
Cedric Roux's avatar
Cedric Roux committed
378
 ** Name:    emm_proc_common_abort()                                   **
Cedric Roux's avatar
 
Cedric Roux committed
379 380
 **                                                                        **
 ** Description: The ongoing EMM procedure has been aborted. The network   **
Cedric Roux's avatar
Cedric Roux committed
381 382 383
 **      performs required actions related to the EMM common pro-  **
 **      cedure previously initiated between the UE with the spe-  **
 **      cified identifier and the MME.                            **
Cedric Roux's avatar
 
Cedric Roux committed
384
 **                                                                        **
Cedric Roux's avatar
Cedric Roux committed
385 386
 ** Inputs:  ueid:      UE lower layer identifier                  **
 **      Others:    _emm_common_data                           **
Cedric Roux's avatar
 
Cedric Roux committed
387
 **                                                                        **
Cedric Roux's avatar
Cedric Roux committed
388 389 390
 ** Outputs:     None                                                      **
 **      Return:    RETURNok, RETURNerror                      **
 **      Others:    None                                       **
Cedric Roux's avatar
 
Cedric Roux committed
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
 **                                                                        **
 ***************************************************************************/
int emm_proc_common_abort(unsigned int ueid)
{
    emm_common_data_t             *emm_common_data_ctx = NULL;
    emm_common_failure_callback_t  emm_callback;

    int rc = RETURNerror;

    LOG_FUNC_IN;

#if defined(EPC_BUILD)
    DevCheck(ueid > 0, ueid, 0, 0);
    emm_common_data_ctx = emm_common_data_context_get(&emm_common_data_head, ueid);
#else
    assert(ueid < EMM_DATA_NB_UE_MAX);
    emm_common_data_ctx = _emm_common_data[ueid];
#endif
    assert(emm_common_data_ctx != NULL);

    emm_callback = emm_common_data_ctx->abort;
    if (emm_callback) {
        struct emm_data_context_s *ctx = NULL;

#if defined(EPC_BUILD)
        ctx = emm_data_context_get(&_emm_data, ueid);
#else
        ctx = _emm_data.ctx[ueid];
#endif
        rc = (*emm_callback)(ctx);
    }

    _emm_common_cleanup(ueid);

    LOG_FUNC_RETURN(rc);
}

/****************************************************************************
 **                                                                        **
Cedric Roux's avatar
Cedric Roux committed
430
 ** Name:    emm_proc_common_get_args()                                **
Cedric Roux's avatar
 
Cedric Roux committed
431 432
 **                                                                        **
 ** Description: Returns pointer to the EMM common procedure argument pa-  **
Cedric Roux's avatar
Cedric Roux committed
433
 **      rameters allocated for the UE with the given identifier.  **
Cedric Roux's avatar
 
Cedric Roux committed
434
 **                                                                        **
Cedric Roux's avatar
Cedric Roux committed
435 436
 ** Inputs:  ueid:      UE lower layer identifier                  **
 **      Others:    _emm_common_data                           **
Cedric Roux's avatar
 
Cedric Roux committed
437
 **                                                                        **
Cedric Roux's avatar
Cedric Roux committed
438 439 440 441
 ** Outputs:     None                                                      **
 **      Return:    pointer to the EMM common procedure argu-  **
 **             ment parameters                            **
 **      Others:    None                                       **
Cedric Roux's avatar
 
Cedric Roux committed
442 443
 **                                                                        **
 ***************************************************************************/
Cedric Roux's avatar
Cedric Roux committed
444
void *emm_proc_common_get_args(unsigned int ueid)
Cedric Roux's avatar
 
Cedric Roux committed
445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466
{
    emm_common_data_t *emm_common_data_ctx = NULL;
    LOG_FUNC_IN;

#if defined(EPC_BUILD)
    DevCheck(ueid > 0, ueid, 0, 0);
    emm_common_data_ctx = emm_common_data_context_get(&emm_common_data_head, ueid);
#else
    assert(ueid < EMM_DATA_NB_UE_MAX);
    emm_common_data_ctx = _emm_common_data[ueid];
#endif
    assert(emm_common_data_ctx != NULL);

    LOG_FUNC_RETURN(emm_common_data_ctx->args);
}

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

/****************************************************************************
 **                                                                        **
Cedric Roux's avatar
Cedric Roux committed
467
 ** Name:    emm_proc_common_cleanup()                                 **
Cedric Roux's avatar
 
Cedric Roux committed
468 469
 **                                                                        **
 ** Description: Cleans EMM procedure callback functions upon completion   **
Cedric Roux's avatar
Cedric Roux committed
470 471 472
 **      of an EMM common procedure previously initiated within an **
 **      EMM procedure currently in progress between the network   **
 **      and the UE with the specified identifier.                 **
Cedric Roux's avatar
 
Cedric Roux committed
473
 **                                                                        **
Cedric Roux's avatar
Cedric Roux committed
474 475
 ** Inputs:  ueid:      UE lower layer identifier                  **
 **      Others:    None                                       **
Cedric Roux's avatar
 
Cedric Roux committed
476
 **                                                                        **
Cedric Roux's avatar
Cedric Roux committed
477 478 479
 ** Outputs:     None                                                      **
 **      Return:    None                                       **
 **      Others:    _emm_common_data                           **
Cedric Roux's avatar
 
Cedric Roux committed
480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496
 **                                                                        **
 ***************************************************************************/
static void _emm_common_cleanup(unsigned int ueid)
{
    emm_common_data_t *emm_common_data_ctx = NULL;

#if defined(EPC_BUILD)
    DevCheck(ueid > 0, ueid, 0, 0);
    emm_common_data_ctx = emm_common_data_context_get(&emm_common_data_head, ueid);
#else
    assert(ueid < EMM_DATA_NB_UE_MAX);
    emm_common_data_ctx = _emm_common_data[ueid];
#endif

    if (emm_common_data_ctx) {
        emm_common_data_ctx->ref_count -= 1;
        if (emm_common_data_ctx->ref_count == 0) {
Cedric Roux's avatar
Cedric Roux committed
497
            /* Release the callback functions */
Cedric Roux's avatar
 
Cedric Roux committed
498 499 500 501 502 503 504
#if defined(EPC_BUILD)
            RB_REMOVE(emm_common_data_map,
                      &emm_common_data_head.emm_common_data_root,
                      emm_common_data_ctx);
#endif
            free(emm_common_data_ctx);
            emm_common_data_ctx = NULL;
Cedric Roux's avatar
Cedric Roux committed
505
        }
Cedric Roux's avatar
 
Cedric Roux committed
506 507 508
    }
}
#endif // NAS_MME