rrc_eNB_S1AP.c 87 KB
Newer Older
1
2
3
4
5
/*
 * 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
Cedric Roux's avatar
Cedric Roux committed
6
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 * 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
 */

winckel's avatar
winckel committed
22
23
/*! \file rrc_eNB_S1AP.c
 * \brief rrc S1AP procedures for eNB
24
 * \author Navid Nikaein, Laurent Winckel, Sebastien ROUX, and Lionel GAUTHIER
25
 * \date 2013-2016
winckel's avatar
winckel committed
26
27
 * \version 1.0
 * \company Eurecom
nikaeinn's avatar
nikaeinn committed
28
 * \email: navid.nikaein@eurecom.fr
winckel's avatar
winckel committed
29
30
 */
#if defined(ENABLE_USE_MME)
31
32
# include "rrc_defs.h"
# include "rrc_extern.h"
winckel's avatar
winckel committed
33
# include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
34
# include "RRC/LTE/MESSAGES/asn1_msg.h"
35
# include "rrc_eNB_UE_context.h"
winckel's avatar
winckel committed
36
# include "rrc_eNB_S1AP.h"
gauthier's avatar
gauthier committed
37
# include "enb_config.h"
38
# include "common/ran_context.h"
39
/****************************************/
40
41
# include "s1ap_eNB_defs.h"
# include "s1ap_eNB_management_procedures.h"
42
43
# include "s1ap_eNB_ue_context.h"
/****************************************/
winckel's avatar
winckel committed
44
45
46
47
48

# if defined(ENABLE_ITTI)
#   include "asn1_conversions.h"
#   include "intertask_interface.h"
#   include "pdcp.h"
49
#   include "pdcp_primitives.h"
winckel's avatar
winckel committed
50
51
52
53
54
#   include "s1ap_eNB.h"
# else
#   include "../../S1AP/s1ap_eNB.h"
# endif

55
56
57
#if defined(ENABLE_SECURITY)
#   include "UTIL/OSA/osa_defs.h"
#endif
58
#include "msc.h"
59

Cedric Roux's avatar
Cedric Roux committed
60
61
#include "UERadioAccessCapabilityInformation.h"

Cedric Roux's avatar
Cedric Roux committed
62
#include "gtpv1u_eNB_task.h"
63
#include "RRC/LTE/rrc_eNB_GTPV1U.h"
Cedric Roux's avatar
Cedric Roux committed
64

65
#include "TLVDecoder.h"
66
#include "S1AP_NAS-PDU.h"
67
#include "flexran_agent_common_internal.h"
Cedric Roux's avatar
Cedric Roux committed
68

69
70
extern RAN_CONTEXT_t RC;

winckel's avatar
winckel committed
71
72
73
/* Value to indicate an invalid UE initial id */
static const uint16_t UE_INITIAL_ID_INVALID = 0;

74
/* Masks for S1AP Encryption algorithms, EEA0 is always supported (not coded) */
75
76
static const uint16_t S1AP_ENCRYPTION_EEA1_MASK = 0x8000;
static const uint16_t S1AP_ENCRYPTION_EEA2_MASK = 0x4000;
77
78

/* Masks for S1AP Integrity algorithms, EIA0 is always supported (not coded) */
79
80
static const uint16_t S1AP_INTEGRITY_EIA1_MASK = 0x8000;
static const uint16_t S1AP_INTEGRITY_EIA2_MASK = 0x4000;
81

82
#if (RRC_VERSION >= MAKE_VERSION(9, 2, 0))
83
84
# define INTEGRITY_ALGORITHM_NONE SecurityAlgorithmConfig__integrityProtAlgorithm_eia0_v920
#else
85
#ifdef EXMIMO_IOT
86
# define INTEGRITY_ALGORITHM_NONE SecurityAlgorithmConfig__integrityProtAlgorithm_eia2
87
#else
88
89
# define INTEGRITY_ALGORITHM_NONE SecurityAlgorithmConfig__integrityProtAlgorithm_reserved
#endif
90
#endif
91

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
void extract_imsi(uint8_t *pdu_buf, uint32_t pdu_len, rrc_eNB_ue_context_t *ue_context_pP)
{
  /* Process NAS message locally to get the IMSI */
  nas_message_t nas_msg;
  memset(&nas_msg, 0, sizeof(nas_message_t));

  int size = 0;

  nas_message_security_header_t *header = &nas_msg.header;
  /* Decode the first octet of the header (security header type or EPS
  * bearer identity, and protocol discriminator) */
  DECODE_U8((char *) pdu_buf, *(uint8_t*) (header), size);

  /* Decode NAS message only if decodable*/
  if (!(header->security_header_type <= SECURITY_HEADER_TYPE_INTEGRITY_PROTECTED
      && header->protocol_discriminator == EPS_MOBILITY_MANAGEMENT_MESSAGE
      && pdu_len > NAS_MESSAGE_SECURITY_HEADER_SIZE))
    return;

  if (header->security_header_type != SECURITY_HEADER_TYPE_NOT_PROTECTED) {
    /* Decode the message authentication code */
    DECODE_U32((char *) pdu_buf+size, header->message_authentication_code, size);
    /* Decode the sequence number */
    DECODE_U8((char *) pdu_buf+size, header->sequence_number, size);
  }

  /* Note: the value of the pointer (i.e. the address) is given by value, so we
   * can modify it as we want. The callee retains the original address! */
  pdu_buf += size;
  pdu_len -= size;
winckel's avatar
winckel committed
122

123
124
125
  /* Decode plain NAS message */
  EMM_msg *e_msg = &nas_msg.plain.emm;
  emm_msg_header_t *emm_header = &e_msg->header;
winckel's avatar
winckel committed
126

127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
  /* First decode the EMM message header */
  int e_head_size = 0;

  /* Check that buffer contains more than only the header */
  if (pdu_len <= sizeof(emm_msg_header_t))
    return;

  /* Decode the security header type and the protocol discriminator */
  DECODE_U8(pdu_buf + e_head_size, *(uint8_t *)(emm_header), e_head_size);
  /* Decode the message type */
  DECODE_U8(pdu_buf + e_head_size, emm_header->message_type, e_head_size);

  /* Check that this is the right message */
  if (emm_header->protocol_discriminator != EPS_MOBILITY_MANAGEMENT_MESSAGE)
    return;

  pdu_buf += e_head_size;
  pdu_len -= e_head_size;

  if (emm_header->message_type == IDENTITY_RESPONSE) {
    decode_identity_response(&e_msg->identity_response, pdu_buf, pdu_len);

    if (e_msg->identity_response.mobileidentity.imsi.typeofidentity == MOBILE_IDENTITY_IMSI) {
      memcpy(&ue_context_pP->ue_context.imsi,
             &e_msg->identity_response.mobileidentity.imsi,
             sizeof(ImsiMobileIdentity_t));
    }
  } else if (emm_header->message_type == ATTACH_REQUEST) {
    decode_attach_request(&e_msg->attach_request, pdu_buf, pdu_len);

    if (e_msg->attach_request.oldgutiorimsi.imsi.typeofidentity == MOBILE_IDENTITY_IMSI) {
      /* the following is very dirty, we cast (implicitly) from
       * ImsiEpsMobileIdentity_t to ImsiMobileIdentity_t*/
      memcpy(&ue_context_pP->ue_context.imsi,
             &e_msg->attach_request.oldgutiorimsi.imsi,
             sizeof(ImsiMobileIdentity_t));
    }
  }
165
}
166

167
# if defined(ENABLE_ITTI)
168
//------------------------------------------------------------------------------
169
/*
170
171
* Get the UE S1 struct containing hashtables S1_id/UE_id.
* Is also used to set the S1_id of the UE, depending on inputs.
172
*/
173
174
175
176
177
178
179
180
struct rrc_ue_s1ap_ids_s*
rrc_eNB_S1AP_get_ue_ids(
  eNB_RRC_INST* const rrc_instance_pP,
  const uint16_t ue_initial_id,
  const uint32_t eNB_ue_s1ap_id
)
//------------------------------------------------------------------------------
{
181
182
  rrc_ue_s1ap_ids_t *result = NULL;
  rrc_ue_s1ap_ids_t *result2 = NULL;
183
184
185
186
  /*****************************/
  instance_t instance = 0;
  s1ap_eNB_instance_t *s1ap_eNB_instance_p = NULL;
  s1ap_eNB_ue_context_t *ue_desc_p = NULL;
187
  rrc_eNB_ue_context_t *ue_context_p = NULL;
188
  /*****************************/
189
190
  hashtable_rc_t     h_rc;

191
192
  if (ue_initial_id != UE_INITIAL_ID_INVALID) {
    h_rc = hashtable_get(rrc_instance_pP->initial_id2_s1ap_ids, (hash_key_t)ue_initial_id, (void**)&result);
193

194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
    if (h_rc == HASH_TABLE_OK) {
      
      if (eNB_ue_s1ap_id > 0) {
        h_rc = hashtable_get(rrc_instance_pP->s1ap_id2_s1ap_ids, (hash_key_t)eNB_ue_s1ap_id, (void**)&result2);
        
        if (h_rc != HASH_TABLE_OK) { // this case is equivalent to associate eNB_ue_s1ap_id and ue_initial_id
          result2 = malloc(sizeof(*result2));
          
          if (NULL != result2) {
            *result2 = *result;
            
            result2->eNB_ue_s1ap_id = eNB_ue_s1ap_id;
            result->eNB_ue_s1ap_id  = eNB_ue_s1ap_id;
            
            h_rc = hashtable_insert(rrc_instance_pP->s1ap_id2_s1ap_ids, (hash_key_t)eNB_ue_s1ap_id, result2);

            if (h_rc != HASH_TABLE_OK) {
              LOG_E(S1AP, "[eNB %ld] Error while hashtable_insert in s1ap_id2_s1ap_ids eNB_ue_s1ap_id %"PRIu32"\n", 
                rrc_instance_pP - RC.rrc[0], 
                eNB_ue_s1ap_id);
            }
          }

        } else { // here we should check that the association was done correctly
          
          if ((result->ue_initial_id != result2->ue_initial_id) || (result->eNB_ue_s1ap_id != result2->eNB_ue_s1ap_id)) {
            
221
222
223
224
            LOG_E(S1AP, "[eNB %ld] Error while hashtable_get, two rrc_ue_s1ap_ids_t that should be equal, are not:\n \
              ue_initial_id 1 = %"PRIu16",\n \
              ue_initial_id 2 = %"PRIu16",\n \
              eNB_ue_s1ap_id 1 = %"PRIu32",\n \
225
226
227
228
229
230
231
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
              eNB_ue_s1ap_id 2 = %"PRIu32"\n",
                rrc_instance_pP - RC.rrc[0],
                result->ue_initial_id,
                result2->ue_initial_id,
                result->eNB_ue_s1ap_id,
                result2->eNB_ue_s1ap_id);

          }

        }
      } // end if if (eNB_ue_s1ap_id > 0)

    } else { // end if (h_rc == HASH_TABLE_OK)

      LOG_E(S1AP, "[eNB %ld] In hashtable_get, couldn't find in initial_id2_s1ap_ids ue_initial_id %"PRIu16"\n", 
        rrc_instance_pP - RC.rrc[0], 
        ue_initial_id);
      /*
      * At the moment this is written, this case shouldn't (cannot) happen and is equivalent to an error.
      * One could try to find the struct instance based on s1ap_id2_s1ap_ids and eNB_ue_s1ap_id (if > 0),
      * but this behavior is not expected at the moment.
      */

    } // end else (h_rc != HASH_TABLE_OK)

  } else { // end if (ue_initial_id != UE_INITIAL_ID_INVALID)

    if (eNB_ue_s1ap_id > 0) {
	    h_rc = hashtable_get(rrc_instance_pP->s1ap_id2_s1ap_ids, (hash_key_t)eNB_ue_s1ap_id, (void**)&result);

      if (h_rc != HASH_TABLE_OK) {
        /*
        * This case is uncommon, but can happen when:
        * -> if the first NAS message was a Detach Request (non exhaustiv), the UE RRC context exist 
        * but is not associated with eNB_ue_s1ap_id
        * -> ... (?)
        */
262
        LOG_E(S1AP, "[eNB %ld] In hashtable_get, couldn't find in s1ap_id2_s1ap_ids eNB_ue_s1ap_id %"PRIu32", trying to find it through S1AP context\n", 
263
264
265
266
267
268
269
270
271
272
          rrc_instance_pP - RC.rrc[0], 
          eNB_ue_s1ap_id);

        instance = ENB_MODULE_ID_TO_INSTANCE(rrc_instance_pP - RC.rrc[0]); // get eNB instance

        s1ap_eNB_instance_p = s1ap_eNB_get_instance(instance); // get s1ap_eNB_instance

        ue_desc_p = s1ap_eNB_get_ue_context(s1ap_eNB_instance_p, eNB_ue_s1ap_id); // get s1ap_eNB_ue_context

        if (ue_desc_p != NULL) {
273

274
275
          result = rrc_eNB_S1AP_get_ue_ids(rrc_instance_pP, ue_desc_p->ue_initial_id, eNB_ue_s1ap_id);

276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
          ue_context_p = rrc_eNB_get_ue_context(RC.rrc[ENB_INSTANCE_TO_MODULE_ID(instance)], result->ue_rnti);

          if ((ue_context_p != NULL) && (ue_context_p->ue_context.eNB_ue_s1ap_id == 0)) {

            ue_context_p->ue_context.eNB_ue_s1ap_id = eNB_ue_s1ap_id;
          
          } else {

            LOG_E(RRC, "[eNB %ld] Incoherence between RRC context and S1AP context (%d != %d) for UE RNTI %d or UE RRC context doesn't exist\n",
              rrc_instance_pP - RC.rrc[0],
              ue_context_p->ue_context.eNB_ue_s1ap_id,
              eNB_ue_s1ap_id,
              result->ue_rnti);

          }

292
293
        } else {

294
          LOG_E(S1AP, "[eNB %ld] In hashtable_get, couldn't find in s1ap_id2_s1ap_ids eNB_ue_s1ap_id %"PRIu32", even when looking at S1AP context\n", 
295
296
297
298
299
300
301
302
303
304
          rrc_instance_pP - RC.rrc[0], 
          eNB_ue_s1ap_id);
          
        }

      } // end if (h_rc != HASH_TABLE_OK)
    } // end if (eNB_ue_s1ap_id > 0)
  } // end else (ue_initial_id == UE_INITIAL_ID_INVALID)

  return result;
305
}
306

307
//------------------------------------------------------------------------------
308
/*
309
* Remove UE ids (ue_initial_id and S1_id) from hashtables.
310
*/
311
312
void
rrc_eNB_S1AP_remove_ue_ids(
313
314
  eNB_RRC_INST *const rrc_instance_pP,
  struct rrc_ue_s1ap_ids_s *const ue_ids_pP
315
316
317
)
//------------------------------------------------------------------------------
{
318
319
  const uint16_t ue_initial_id  = ue_ids_pP->ue_initial_id;
  const uint32_t eNB_ue_s1ap_id = ue_ids_pP->eNB_ue_s1ap_id;
320

321
  hashtable_rc_t h_rc;
322

323
324
325
  if (rrc_instance_pP == NULL) {
    LOG_E(RRC, "Bad RRC instance\n");
    return;
326
327
  }

328
329
330
  if (ue_ids_pP == NULL) {
    LOG_E(RRC, "Trying to free a NULL S1AP UE IDs\n");
    return;
winckel's avatar
winckel committed
331
  }
332

333
  if (eNB_ue_s1ap_id > 0) {
334
335
336
337
338
339
340
	  h_rc = hashtable_remove(rrc_instance_pP->s1ap_id2_s1ap_ids, (hash_key_t)eNB_ue_s1ap_id);
	
    if (h_rc != HASH_TABLE_OK) {
	    LOG_W(RRC, "S1AP Did not find entry in hashtable s1ap_id2_s1ap_ids for eNB_ue_s1ap_id %u\n", eNB_ue_s1ap_id);
	  } else {
	    LOG_W(RRC, "S1AP removed entry in hashtable s1ap_id2_s1ap_ids for eNB_ue_s1ap_id %u\n", eNB_ue_s1ap_id);
	  }
341
342
343
344
  }

  if (ue_initial_id != UE_INITIAL_ID_INVALID) {
    h_rc = hashtable_remove(rrc_instance_pP->initial_id2_s1ap_ids, (hash_key_t)ue_initial_id);
345
346
347
348
349
350
 
    if (h_rc != HASH_TABLE_OK) {
      LOG_W(RRC, "S1AP Did not find entry in hashtable initial_id2_s1ap_ids for ue_initial_id %u\n", ue_initial_id);
    } else {
      LOG_W(RRC, "S1AP removed entry in hashtable initial_id2_s1ap_ids for ue_initial_id %u\n", ue_initial_id);
    }
351
  }
winckel's avatar
winckel committed
352
353
}

354
355
/*! \fn uint16_t get_next_ue_initial_id(uint8_t mod_id)
 *\brief provide an UE initial ID for S1AP initial communication.
winckel's avatar
winckel committed
356
 *\param mod_id Instance ID of eNB.
357
 *\return the UE initial ID.
winckel's avatar
winckel committed
358
 */
359
360
361
362
363
364
//------------------------------------------------------------------------------
static uint16_t
get_next_ue_initial_id(
  const module_id_t mod_id
)
//------------------------------------------------------------------------------
365
{
366
367
  static uint16_t ue_initial_id[NUMBER_OF_eNB_MAX];
  ue_initial_id[mod_id]++;
winckel's avatar
winckel committed
368

369
370
371
372
  /* Never use UE_INITIAL_ID_INVALID this is the invalid id! */
  if (ue_initial_id[mod_id] == UE_INITIAL_ID_INVALID) {
    ue_initial_id[mod_id]++;
  }
winckel's avatar
winckel committed
373

374
  return ue_initial_id[mod_id];
375
}
376

377
378


winckel's avatar
winckel committed
379

winckel's avatar
winckel committed
380
/*! \fn uint8_t get_UE_index_from_s1ap_ids(uint8_t mod_id, uint16_t ue_initial_id, uint32_t eNB_ue_s1ap_id)
winckel's avatar
winckel committed
381
382
383
384
385
386
387
 *\brief retrieve UE index in the eNB from the UE initial ID if not equal to UE_INDEX_INVALID or
 *\brief from the eNB_ue_s1ap_id previously transmitted by S1AP.
 *\param mod_id Instance ID of eNB.
 *\param ue_initial_id The UE initial ID sent to S1AP.
 *\param eNB_ue_s1ap_id The value sent by S1AP.
 *\return the UE index or UE_INDEX_INVALID if not found.
 */
388
389
390
391
392
393
static struct rrc_eNB_ue_context_s*
rrc_eNB_get_ue_context_from_s1ap_ids(
  const instance_t  instanceP,
  const uint16_t    ue_initial_idP,
  const uint32_t    eNB_ue_s1ap_idP
)
394
{
395
396
  rrc_ue_s1ap_ids_t* temp = NULL;

397
  temp = rrc_eNB_S1AP_get_ue_ids(RC.rrc[ENB_INSTANCE_TO_MODULE_ID(instanceP)], ue_initial_idP, eNB_ue_s1ap_idP);
winckel's avatar
winckel committed
398

399
400
  if (temp != NULL) {
    return rrc_eNB_get_ue_context(RC.rrc[ENB_INSTANCE_TO_MODULE_ID(instanceP)], temp->ue_rnti);
winckel's avatar
winckel committed
401
402
  }

403
  return NULL;
winckel's avatar
winckel committed
404
405
}

406
407
408
409
410
/*! \fn e_SecurityAlgorithmConfig__cipheringAlgorithm rrc_eNB_select_ciphering(uint16_t algorithms)
 *\brief analyze available encryption algorithms bit mask and return the relevant one.
 *\param algorithms The bit mask of available algorithms received from S1AP.
 *\return the selected algorithm.
 */
Cedric Roux's avatar
Cedric Roux committed
411
static CipheringAlgorithm_r12_t rrc_eNB_select_ciphering(uint16_t algorithms)
412
413
{

414
//#warning "Forced   return SecurityAlgorithmConfig__cipheringAlgorithm_eea0, to be deleted in future"
Cedric Roux's avatar
Cedric Roux committed
415
  return CipheringAlgorithm_r12_eea0;
416

417
  if (algorithms & S1AP_ENCRYPTION_EEA2_MASK) {
Cedric Roux's avatar
Cedric Roux committed
418
    return CipheringAlgorithm_r12_eea2;
419
420
421
  }

  if (algorithms & S1AP_ENCRYPTION_EEA1_MASK) {
Cedric Roux's avatar
Cedric Roux committed
422
    return CipheringAlgorithm_r12_eea1;
423
424
  }

Cedric Roux's avatar
Cedric Roux committed
425
  return CipheringAlgorithm_r12_eea0;
426
427
428
429
430
431
432
}

/*! \fn e_SecurityAlgorithmConfig__integrityProtAlgorithm rrc_eNB_select_integrity(uint16_t algorithms)
 *\brief analyze available integrity algorithms bit mask and return the relevant one.
 *\param algorithms The bit mask of available algorithms received from S1AP.
 *\return the selected algorithm.
 */
433
434
435
static e_SecurityAlgorithmConfig__integrityProtAlgorithm rrc_eNB_select_integrity(uint16_t algorithms)
{

436
  if (algorithms & S1AP_INTEGRITY_EIA2_MASK) {
437
    return SecurityAlgorithmConfig__integrityProtAlgorithm_eia2;
438
439
440
  }

  if (algorithms & S1AP_INTEGRITY_EIA1_MASK) {
441
    return SecurityAlgorithmConfig__integrityProtAlgorithm_eia1;
442
443
444
445
446
447
448
449
450
451
452
453
  }

  return INTEGRITY_ALGORITHM_NONE;
}

/*! \fn int rrc_eNB_process_security (uint8_t mod_id, uint8_t ue_index, security_capabilities_t *security_capabilities)
 *\brief save and analyze available security algorithms bit mask and select relevant ones.
 *\param mod_id Instance ID of eNB.
 *\param ue_index Instance ID of UE in the eNB.
 *\param security_capabilities The security capabilities received from S1AP.
 *\return TRUE if at least one algorithm has been changed else FALSE.
 */
454
455
456
457
458
459
static int
rrc_eNB_process_security(
  const protocol_ctxt_t* const ctxt_pP,
  rrc_eNB_ue_context_t*          const ue_context_pP,
  security_capabilities_t* security_capabilities_pP
)
460
{
461
  boolean_t                                         changed = FALSE;
Cedric Roux's avatar
Cedric Roux committed
462
  CipheringAlgorithm_r12_t                          cipheringAlgorithm;
463
464
465
  e_SecurityAlgorithmConfig__integrityProtAlgorithm integrityProtAlgorithm;

  /* Save security parameters */
466
  ue_context_pP->ue_context.security_capabilities = *security_capabilities_pP;
467

468
469
  // translation
  LOG_D(RRC,
Cedric Roux's avatar
Cedric Roux committed
470
        "[eNB %d] NAS security_capabilities.encryption_algorithms %u AS ciphering_algorithm %lu NAS security_capabilities.integrity_algorithms %u AS integrity_algorithm %u\n",
471
472
        ctxt_pP->module_id,
        ue_context_pP->ue_context.security_capabilities.encryption_algorithms,
Cedric Roux's avatar
Cedric Roux committed
473
        (unsigned long)ue_context_pP->ue_context.ciphering_algorithm,
474
475
        ue_context_pP->ue_context.security_capabilities.integrity_algorithms,
        ue_context_pP->ue_context.integrity_algorithm);
476
  /* Select relevant algorithms */
477
  cipheringAlgorithm = rrc_eNB_select_ciphering (ue_context_pP->ue_context.security_capabilities.encryption_algorithms);
478

479
480
  if (ue_context_pP->ue_context.ciphering_algorithm != cipheringAlgorithm) {
    ue_context_pP->ue_context.ciphering_algorithm = cipheringAlgorithm;
481
    changed = TRUE;
482
483
  }

484
  integrityProtAlgorithm = rrc_eNB_select_integrity (ue_context_pP->ue_context.security_capabilities.integrity_algorithms);
485

486
487
  if (ue_context_pP->ue_context.integrity_algorithm != integrityProtAlgorithm) {
    ue_context_pP->ue_context.integrity_algorithm = integrityProtAlgorithm;
488
    changed = TRUE;
489
490
  }

Cedric Roux's avatar
Cedric Roux committed
491
  LOG_I (RRC, "[eNB %d][UE %x] Selected security algorithms (%p): %lx, %x, %s\n",
492
493
494
         ctxt_pP->module_id,
         ue_context_pP->ue_context.rnti,
         security_capabilities_pP,
Cedric Roux's avatar
Cedric Roux committed
495
         (unsigned long)cipheringAlgorithm,
496
497
         integrityProtAlgorithm,
         changed ? "changed" : "same");
498
499
500
501

  return changed;
}

502
/*! \fn void process_eNB_security_key (const protocol_ctxt_t* const ctxt_pP, eNB_RRC_UE_t * const ue_context_pP, uint8_t *security_key)
503
 *\brief save security key.
504
505
506
 *\param ctxt_pP         Running context.
 *\param ue_context_pP   UE context.
 *\param security_key_pP The security key received from S1AP.
507
 */
508
509
510
511
512
513
514
//------------------------------------------------------------------------------
static void process_eNB_security_key (
  const protocol_ctxt_t* const ctxt_pP,
  rrc_eNB_ue_context_t*          const ue_context_pP,
  uint8_t*               security_key_pP
)
//------------------------------------------------------------------------------
515
{
516
517
518
519
520
#if defined(ENABLE_SECURITY)
  char ascii_buffer[65];
  uint8_t i;

  /* Saves the security key */
521
  memcpy (ue_context_pP->ue_context.kenb, security_key_pP, SECURITY_KEY_LENGTH);
522
523
  memset (ue_context_pP->ue_context.nh, 0, SECURITY_KEY_LENGTH);
  ue_context_pP->ue_context.nh_ncc = -1;
524
525

  for (i = 0; i < 32; i++) {
526
    sprintf(&ascii_buffer[2 * i], "%02X", ue_context_pP->ue_context.kenb[i]);
527
  }
528

529
530
  ascii_buffer[2 * i] = '\0';

531
  LOG_I (RRC, "[eNB %d][UE %x] Saved security key %s\n", ctxt_pP->module_id, ue_context_pP->ue_context.rnti, ascii_buffer);
532
533
534
#endif
}

535

536
//------------------------------------------------------------------------------
537
void
538
539
540
541
542
543
rrc_pdcp_config_security(
  const protocol_ctxt_t* const ctxt_pP,
  rrc_eNB_ue_context_t*          const ue_context_pP,
  const uint8_t send_security_mode_command
)
//------------------------------------------------------------------------------
544
{
545
546
547

#if defined(ENABLE_SECURITY)

548

549
  SRB_ToAddModList_t*                 SRB_configList = ue_context_pP->ue_context.SRB_configList;
550
551
552
553
  uint8_t                            *kRRCenc = NULL;
  uint8_t                            *kRRCint = NULL;
  uint8_t                            *kUPenc = NULL;
  pdcp_t                             *pdcp_p   = NULL;
554
  static int                          print_keys= 1;
555
556
  hashtable_rc_t                      h_rc;
  hash_key_t                          key;
557

558
559
  /* Derive the keys from kenb */
  if (SRB_configList != NULL) {
560
561
562
    derive_key_up_enc(ue_context_pP->ue_context.ciphering_algorithm,
                      ue_context_pP->ue_context.kenb,
                      &kUPenc);
563
  }
564

565
566
567
568
569
570
  derive_key_rrc_enc(ue_context_pP->ue_context.ciphering_algorithm,
                     ue_context_pP->ue_context.kenb,
                     &kRRCenc);
  derive_key_rrc_int(ue_context_pP->ue_context.integrity_algorithm,
                     ue_context_pP->ue_context.kenb,
                     &kRRCint);
571

572
#if !defined(USRP_REC_PLAY)
573
  SET_LOG_DUMP(DEBUG_SECURITY) ;
574
575
#endif
  
576

577
578
579
  if ( LOG_DUMPFLAG( DEBUG_SECURITY ) ) {
    if (print_keys ==1 ) {
      print_keys =0;
580

581
582
583
      LOG_DUMPMSG(RRC, DEBUG_SECURITY, ue_context_pP->ue_context.kenb, 32,"\nKeNB:" );
      LOG_DUMPMSG(RRC, DEBUG_SECURITY, kRRCenc, 32,"\nKRRCenc:" );
      LOG_DUMPMSG(RRC, DEBUG_SECURITY, kRRCint, 32,"\nKRRCint:" );
584
    }
585
586
  }

587
588
  key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, DCCH, SRB_FLAG_YES);
  h_rc = hashtable_get(pdcp_coll_p, key, (void**)&pdcp_p);
589
590


591
  if (h_rc == HASH_TABLE_OK) {
592
    pdcp_config_set_security(
593
      ctxt_pP,
594
595
596
597
      pdcp_p,
      DCCH,
      DCCH+2,
      (send_security_mode_command == TRUE)  ?
598
599
600
      0 | (ue_context_pP->ue_context.integrity_algorithm << 4) :
      (ue_context_pP->ue_context.ciphering_algorithm )         |
      (ue_context_pP->ue_context.integrity_algorithm << 4),
601
602
603
      kRRCenc,
      kRRCint,
      kUPenc);
604
605
606
607
608
609
  } else {
    LOG_E(RRC,
          PROTOCOL_RRC_CTXT_UE_FMT"Could not get PDCP instance for SRB DCCH %u\n",
          PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
          DCCH);
  }
610

611
#endif
612
613
}

614
615
616
617
618
619
620
//------------------------------------------------------------------------------
void
rrc_eNB_send_S1AP_INITIAL_CONTEXT_SETUP_RESP(
  const protocol_ctxt_t* const ctxt_pP,
  rrc_eNB_ue_context_t*          const ue_context_pP
)
//------------------------------------------------------------------------------
621
{
622
  MessageDef      *msg_p         = NULL;
winckel's avatar
winckel committed
623
624
625
626
627
  int e_rab;
  int e_rabs_done = 0;
  int e_rabs_failed = 0;

  msg_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_INITIAL_CONTEXT_SETUP_RESP);
628
  S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p).eNB_ue_s1ap_id = ue_context_pP->ue_context.eNB_ue_s1ap_id;
629

630
631
  for (e_rab = 0; e_rab < ue_context_pP->ue_context.nb_of_e_rabs; e_rab++) {
    if (ue_context_pP->ue_context.e_rab[e_rab].status == E_RAB_STATUS_DONE) {
winckel's avatar
winckel committed
632
      e_rabs_done++;
633
      S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p).e_rabs[e_rab].e_rab_id = ue_context_pP->ue_context.e_rab[e_rab].param.e_rab_id;
winckel's avatar
winckel committed
634
      // TODO add other information from S1-U when it will be integrated
635
636
      S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p).e_rabs[e_rab].gtp_teid = ue_context_pP->ue_context.enb_gtp_teid[e_rab];
      S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p).e_rabs[e_rab].eNB_addr = ue_context_pP->ue_context.enb_gtp_addrs[e_rab];
637
      S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p).e_rabs[e_rab].eNB_addr.length = 4;
638
      ue_context_pP->ue_context.e_rab[e_rab].status = E_RAB_STATUS_ESTABLISHED;
639
    } else {
winckel's avatar
winckel committed
640
      e_rabs_failed++;
641
      ue_context_pP->ue_context.e_rab[e_rab].status = E_RAB_STATUS_FAILED;
642
      S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p).e_rabs_failed[e_rab].e_rab_id = ue_context_pP->ue_context.e_rab[e_rab].param.e_rab_id;
winckel's avatar
winckel committed
643
644
645
      // TODO add cause when it will be integrated
    }
  }
gauthier's avatar
gauthier committed
646
647

  MSC_LOG_TX_MESSAGE(
648
649
650
651
652
653
654
655
656
    MSC_RRC_ENB,
    MSC_S1AP_ENB,
    (const char *)&S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p),
    sizeof(s1ap_initial_context_setup_resp_t),
    MSC_AS_TIME_FMT" INITIAL_CONTEXT_SETUP_RESP UE %X eNB_ue_s1ap_id %u e_rabs:%u succ %u fail",
    MSC_AS_TIME_ARGS(ctxt_pP),
    ue_context_pP->ue_id_rnti,
    S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p).eNB_ue_s1ap_id,
    e_rabs_done, e_rabs_failed);
gauthier's avatar
gauthier committed
657

658

winckel's avatar
winckel committed
659
660
661
  S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p).nb_of_e_rabs = e_rabs_done;
  S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p).nb_of_e_rabs_failed = e_rabs_failed;

662
  itti_send_msg_to_task (TASK_S1AP, ctxt_pP->instance, msg_p);
winckel's avatar
winckel committed
663
664
665
}
# endif

666
667
668
669
670
671
672
673
//------------------------------------------------------------------------------
void
rrc_eNB_send_S1AP_UPLINK_NAS(
  const protocol_ctxt_t*    const ctxt_pP,
  rrc_eNB_ue_context_t*             const ue_context_pP,
  UL_DCCH_Message_t*        const ul_dcch_msg
)
//------------------------------------------------------------------------------
674
{
winckel's avatar
winckel committed
675
676
677
678
679
#if defined(ENABLE_ITTI)
  {
    ULInformationTransfer_t *ulInformationTransfer = &ul_dcch_msg->message.choice.c1.choice.ulInformationTransfer;

    if ((ulInformationTransfer->criticalExtensions.present == ULInformationTransfer__criticalExtensions_PR_c1)
680
681
682
683
    && (ulInformationTransfer->criticalExtensions.choice.c1.present
    == ULInformationTransfer__criticalExtensions__c1_PR_ulInformationTransfer_r8)
    && (ulInformationTransfer->criticalExtensions.choice.c1.choice.ulInformationTransfer_r8.dedicatedInfoType.present
    == ULInformationTransfer_r8_IEs__dedicatedInfoType_PR_dedicatedInfoNAS)) {
winckel's avatar
winckel committed
684
685
686
687
688
689
690
691
692
693
694
      /* This message hold a dedicated info NAS payload, forward it to NAS */
      struct ULInformationTransfer_r8_IEs__dedicatedInfoType *dedicatedInfoType =
          &ulInformationTransfer->criticalExtensions.choice.c1.choice.ulInformationTransfer_r8.dedicatedInfoType;
      uint32_t pdu_length;
      uint8_t *pdu_buffer;
      MessageDef *msg_p;

      pdu_length = dedicatedInfoType->choice.dedicatedInfoNAS.size;
      pdu_buffer = dedicatedInfoType->choice.dedicatedInfoNAS.buf;

      msg_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_UPLINK_NAS);
695
      S1AP_UPLINK_NAS (msg_p).eNB_ue_s1ap_id = ue_context_pP->ue_context.eNB_ue_s1ap_id;
winckel's avatar
winckel committed
696
697
698
      S1AP_UPLINK_NAS (msg_p).nas_pdu.length = pdu_length;
      S1AP_UPLINK_NAS (msg_p).nas_pdu.buffer = pdu_buffer;

699
700
701
      extract_imsi(S1AP_UPLINK_NAS (msg_p).nas_pdu.buffer,
                   S1AP_UPLINK_NAS (msg_p).nas_pdu.length,
                   ue_context_pP);
702

703
      itti_send_msg_to_task (TASK_S1AP, ctxt_pP->instance, msg_p);
winckel's avatar
winckel committed
704
705
706
707
708
709
710
711
712
713
    }
  }
#else
  {
    ULInformationTransfer_t *ulInformationTransfer;
    ulInformationTransfer =
    &ul_dcch_msg->message.choice.c1.choice.
    ulInformationTransfer;

    if (ulInformationTransfer->criticalExtensions.present ==
714
    ULInformationTransfer__criticalExtensions_PR_c1) {
winckel's avatar
winckel committed
715
      if (ulInformationTransfer->criticalExtensions.choice.c1.present ==
716
      ULInformationTransfer__criticalExtensions__c1_PR_ulInformationTransfer_r8) {
winckel's avatar
winckel committed
717
718
719
720
721
722

        ULInformationTransfer_r8_IEs_t
        *ulInformationTransferR8;
        ulInformationTransferR8 =
        &ulInformationTransfer->criticalExtensions.choice.
        c1.choice.ulInformationTransfer_r8;
723

724
725
726
        if (ulInformationTransferR8->dedicatedInfoType.present ==
            ULInformationTransfer_r8_IEs__dedicatedInfoType_PR_dedicatedInfoNAS) {

727
728
729
          extract_imsi(ulInformationTransferR8->dedicatedInfoType.choice.dedicatedInfoNAS.buf,
                       ulInformationTransferR8->dedicatedInfoType.choice.dedicatedInfoNAS.size,
                       ue_context_pP);
730

731
          s1ap_eNB_new_data_request (mod_id, ue_index,
732
733
734
              ulInformationTransferR8->dedicatedInfoType.choice.dedicatedInfoNAS.buf,
              ulInformationTransferR8->dedicatedInfoType.choice.dedicatedInfoNAS.size);
        }
winckel's avatar
winckel committed
735
736
737
738
739
740
      }
    }
  }
#endif
}

741
742
743
744
745
746
747
//------------------------------------------------------------------------------
void rrc_eNB_send_S1AP_UE_CAPABILITIES_IND(
  const protocol_ctxt_t* const ctxt_pP,
  rrc_eNB_ue_context_t*          const ue_context_pP,
  UL_DCCH_Message_t* ul_dcch_msg
)
//------------------------------------------------------------------------------
748
{
749
  UECapabilityInformation_t *ueCapabilityInformation = &ul_dcch_msg->message.choice.c1.choice.ueCapabilityInformation;
Cedric Roux's avatar
Cedric Roux committed
750
751
752
753
754
755
756
757
758
  /* 4096 is arbitrary, should be big enough */
  unsigned char buf[4096];
  unsigned char *buf2;
  UERadioAccessCapabilityInformation_t rac;

  if (ueCapabilityInformation->criticalExtensions.present != UECapabilityInformation__criticalExtensions_PR_c1
      || ueCapabilityInformation->criticalExtensions.choice.c1.present != UECapabilityInformation__criticalExtensions__c1_PR_ueCapabilityInformation_r8) {
    LOG_E(RRC, "[eNB %d][UE %x] bad UE capabilities\n", ctxt_pP->module_id, ue_context_pP->ue_context.rnti);
    return;
759
  }
Cedric Roux's avatar
Cedric Roux committed
760

761
762
  asn_enc_rval_t ret = uper_encode_to_buffer(&asn_DEF_UECapabilityInformation, NULL, ueCapabilityInformation, buf, 4096);

Cedric Roux's avatar
Cedric Roux committed
763
764
765
766
767
768
769
770
771
772
773
774
775
  if (ret.encoded == -1) abort();

  memset(&rac, 0, sizeof(UERadioAccessCapabilityInformation_t));

  rac.criticalExtensions.present = UERadioAccessCapabilityInformation__criticalExtensions_PR_c1;
  rac.criticalExtensions.choice.c1.present = UERadioAccessCapabilityInformation__criticalExtensions__c1_PR_ueRadioAccessCapabilityInformation_r8;
  rac.criticalExtensions.choice.c1.choice.ueRadioAccessCapabilityInformation_r8.ue_RadioAccessCapabilityInfo.buf = buf;
  rac.criticalExtensions.choice.c1.choice.ueRadioAccessCapabilityInformation_r8.ue_RadioAccessCapabilityInfo.size = (ret.encoded+7)/8;
  rac.criticalExtensions.choice.c1.choice.ueRadioAccessCapabilityInformation_r8.nonCriticalExtension = NULL;

  /* 8192 is arbitrary, should be big enough */
  buf2 = malloc16(8192);
  if (buf2 == NULL) abort();
776
777
778

  ret = uper_encode_to_buffer(&asn_DEF_UERadioAccessCapabilityInformation, NULL, &rac, buf2, 8192);

Cedric Roux's avatar
Cedric Roux committed
779
780
781
782
783
784
785
786
787
788
  if (ret.encoded == -1) abort();

  MessageDef *msg_p;

  msg_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_UE_CAPABILITIES_IND);
  S1AP_UE_CAPABILITIES_IND (msg_p).eNB_ue_s1ap_id = ue_context_pP->ue_context.eNB_ue_s1ap_id;
  S1AP_UE_CAPABILITIES_IND (msg_p).ue_radio_cap.length = (ret.encoded+7)/8;
  S1AP_UE_CAPABILITIES_IND (msg_p).ue_radio_cap.buffer = buf2;

  itti_send_msg_to_task (TASK_S1AP, ctxt_pP->instance, msg_p);
789
790
}

791
//------------------------------------------------------------------------------
792
/*
793
* Initial UE NAS message on S1AP.
794
*/
795
796
797
void
rrc_eNB_send_S1AP_NAS_FIRST_REQ(
  const protocol_ctxt_t* const ctxt_pP,
798
  rrc_eNB_ue_context_t* const ue_context_pP,
799
800
801
  RRCConnectionSetupComplete_r8_IEs_t* rrcConnectionSetupComplete
)
//------------------------------------------------------------------------------
802
{
803
804
  eNB_RRC_INST *rrc = RC.rrc[ctxt_pP->module_id];

winckel's avatar
winckel committed
805
806
#if defined(ENABLE_ITTI)
  {
807
808
    MessageDef*         message_p         = NULL;
    rrc_ue_s1ap_ids_t*  rrc_ue_s1ap_ids_p = NULL;
809
    hashtable_rc_t      h_rc;
winckel's avatar
winckel committed
810

811
    message_p = itti_alloc_new_message(TASK_RRC_ENB, S1AP_NAS_FIRST_REQ);
812
813
    memset(&message_p->ittiMsg.s1ap_nas_first_req, 0, sizeof(s1ap_nas_first_req_t));

814
815
816
    ue_context_pP->ue_context.ue_initial_id = get_next_ue_initial_id(ctxt_pP->module_id);
    
    S1AP_NAS_FIRST_REQ(message_p).ue_initial_id = ue_context_pP->ue_context.ue_initial_id;
817
818
819
820
821
822

    rrc_ue_s1ap_ids_p = malloc(sizeof(*rrc_ue_s1ap_ids_p));
    rrc_ue_s1ap_ids_p->ue_initial_id  = ue_context_pP->ue_context.ue_initial_id;
    rrc_ue_s1ap_ids_p->eNB_ue_s1ap_id = UE_INITIAL_ID_INVALID;
    rrc_ue_s1ap_ids_p->ue_rnti        = ctxt_pP->rnti;

823
    h_rc = hashtable_insert(RC.rrc[ctxt_pP->module_id]->initial_id2_s1ap_ids,
824
825
826
    		                (hash_key_t)ue_context_pP->ue_context.ue_initial_id,
    		                rrc_ue_s1ap_ids_p);

827
    if (h_rc != HASH_TABLE_OK) {
828
      LOG_E(S1AP, "[eNB %d] Error while hashtable_insert in initial_id2_s1ap_ids ue_initial_id %u\n",
829
830
        ctxt_pP->module_id, 
        ue_context_pP->ue_context.ue_initial_id);
831
    }
winckel's avatar
winckel committed
832
833

    /* Assume that cause is coded in the same way in RRC and S1ap, just check that the value is in S1ap range */
834
    AssertFatal(ue_context_pP->ue_context.establishment_cause < RRC_CAUSE_LAST,
835
836
837
838
      "Establishment cause invalid (%jd/%d) for eNB %d!",
      ue_context_pP->ue_context.establishment_cause, 
      RRC_CAUSE_LAST, 
      ctxt_pP->module_id);
839
840

    S1AP_NAS_FIRST_REQ (message_p).establishment_cause = ue_context_pP->ue_context.establishment_cause;
winckel's avatar
winckel committed
841

842
843
    /* Forward NAS message */ 
    S1AP_NAS_FIRST_REQ (message_p).nas_pdu.buffer = rrcConnectionSetupComplete->dedicatedInfoNAS.buf;
winckel's avatar
winckel committed
844
845
    S1AP_NAS_FIRST_REQ (message_p).nas_pdu.length = rrcConnectionSetupComplete->dedicatedInfoNAS.size;

846
847
848
    extract_imsi(S1AP_NAS_FIRST_REQ (message_p).nas_pdu.buffer,
                 S1AP_NAS_FIRST_REQ (message_p).nas_pdu.length,
                 ue_context_pP);
849

winckel's avatar
winckel committed
850
851
852
853
    /* Fill UE identities with available information */
    {
      S1AP_NAS_FIRST_REQ (message_p).ue_identity.presenceMask = UE_IDENTITIES_NONE;

854
      if (ue_context_pP->ue_context.Initialue_identity_s_TMSI.presence) {
winckel's avatar
winckel committed
855
        /* Fill s-TMSI */
856
        UE_S_TMSI* s_TMSI = &ue_context_pP->ue_context.Initialue_identity_s_TMSI;
winckel's avatar
winckel committed
857
858
859
860

        S1AP_NAS_FIRST_REQ (message_p).ue_identity.presenceMask |= UE_IDENTITIES_s_tmsi;
        S1AP_NAS_FIRST_REQ (message_p).ue_identity.s_tmsi.mme_code = s_TMSI->mme_code;
        S1AP_NAS_FIRST_REQ (message_p).ue_identity.s_tmsi.m_tmsi = s_TMSI->m_tmsi;
861

862
        LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ with s_TMSI: MME code %u M-TMSI %u ue %x\n",
gauthier's avatar
gauthier committed
863
864
865
866
            ctxt_pP->module_id,
            S1AP_NAS_FIRST_REQ (message_p).ue_identity.s_tmsi.mme_code,
            S1AP_NAS_FIRST_REQ (message_p).ue_identity.s_tmsi.m_tmsi,
            ue_context_pP->ue_context.rnti);
867
      } // end if S-TMSI presence
winckel's avatar
winckel committed
868

869
870
      /* selected_plmn_identity: IE is 1-based, convert to 0-based (C array) */
      int selected_plmn_identity = rrcConnectionSetupComplete->selectedPLMN_Identity - 1;
871
      S1AP_NAS_FIRST_REQ(message_p).selected_plmn_identity = selected_plmn_identity;
872

winckel's avatar
winckel committed
873
874
875
876
877
      if (rrcConnectionSetupComplete->registeredMME != NULL) {
        /* Fill GUMMEI */
        struct RegisteredMME *r_mme = rrcConnectionSetupComplete->registeredMME;

        S1AP_NAS_FIRST_REQ (message_p).ue_identity.presenceMask |= UE_IDENTITIES_gummei;
878

winckel's avatar
winckel committed
879
880
881
        if (r_mme->plmn_Identity != NULL) {
          if ((r_mme->plmn_Identity->mcc != NULL) && (r_mme->plmn_Identity->mcc->list.count > 0)) {
            /* Use first indicated PLMN MCC if it is defined */
882
            S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc = *r_mme->plmn_Identity->mcc->list.array[selected_plmn_identity];
883
            
884
            LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MCC %u ue %x\n",
885
886
887
              ctxt_pP->module_id,
              S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc,
              ue_context_pP->ue_context.rnti);
winckel's avatar
winckel committed
888
          }
889

winckel's avatar
winckel committed
890
891
          if (r_mme->plmn_Identity->mnc.list.count > 0) {
            /* Use first indicated PLMN MNC if it is defined */
892
            S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc = *r_mme->plmn_Identity->mnc.list.array[selected_plmn_identity];
893
            
894
            LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MNC %u ue %x\n",
895
896
897
              ctxt_pP->module_id,
              S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc,
              ue_context_pP->ue_context.rnti);
winckel's avatar
winckel committed
898
          }
899
900

        } else { // end if plmn_Identity != NULL
901
902
903
          S1AP_NAS_FIRST_REQ(message_p).ue_identity.gummei.mcc = rrc->configuration.mcc[selected_plmn_identity];
          S1AP_NAS_FIRST_REQ(message_p).ue_identity.gummei.mnc = rrc->configuration.mnc[selected_plmn_identity];
          S1AP_NAS_FIRST_REQ(message_p).ue_identity.gummei.mnc_len = rrc->configuration.mnc_digit_length[selected_plmn_identity];
904
        } // end else (plmn_Identity == NULL)
905

gauthier's avatar
gauthier committed
906
        S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_code     = BIT_STRING_to_uint8 (&r_mme->mmec);
winckel's avatar
winckel committed
907
        S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_group_id = BIT_STRING_to_uint16 (&r_mme->mmegi);
gauthier's avatar
gauthier committed
908

909
        MSC_LOG_TX_MESSAGE(MSC_S1AP_ENB,
910
911
912
913
914
915
916
          MSC_S1AP_MME,
          (const char *)&message_p->ittiMsg.s1ap_nas_first_req,
          sizeof(s1ap_nas_first_req_t),
          MSC_AS_TIME_FMT" S1AP_NAS_FIRST_REQ eNB %u UE %x",
          MSC_AS_TIME_ARGS(ctxt_pP),
          ctxt_pP->module_id,
          ctxt_pP->rnti);
gauthier's avatar
gauthier committed
917

918
919
        LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI mme_code %u mme_group_id %u ue %x\n",
              ctxt_pP->module_id,
920
921
              S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_code,
              S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_group_id,
922
              ue_context_pP->ue_context.rnti);
923
924
925
926

      } // end if MME info present
    } // end "Fill UE identities with available information" sub-part

927
    itti_send_msg_to_task (TASK_S1AP, ctxt_pP->instance, message_p);
winckel's avatar
winckel committed
928
  }
929

winckel's avatar
winckel committed
930
#else
931

winckel's avatar
winckel committed
932
  {
933
934
935
    s1ap_eNB_new_data_request (
      ctxt_pP->module_id,
      ue_context_pP,
936
937
938
939
      rrcConnectionSetupComplete->dedicatedInfoNAS.
      buf,
      rrcConnectionSetupComplete->dedicatedInfoNAS.
      size);
winckel's avatar
winckel committed
940
  }
941

winckel's avatar
winckel committed
942
943
944
945
#endif
}

# if defined(ENABLE_ITTI)
946
947
948
949
950
951
952
953
954
//------------------------------------------------------------------------------
int
rrc_eNB_process_S1AP_DOWNLINK_NAS(
  MessageDef* msg_p,
  const char* msg_name,
  instance_t instance,
  mui_t* rrc_eNB_mui
)
//------------------------------------------------------------------------------
955
{
956
957
  uint16_t ue_initial_id;
  uint32_t eNB_ue_s1ap_id;
winckel's avatar
winckel committed
958
959
  uint32_t length;
  uint8_t *buffer;
960
961
  uint8_t srb_id; 
  
962
963
  struct rrc_eNB_ue_context_s* ue_context_p = NULL;
  protocol_ctxt_t              ctxt;
964
965
  ue_initial_id = S1AP_DOWNLINK_NAS (msg_p).ue_initial_id;
  eNB_ue_s1ap_id = S1AP_DOWNLINK_NAS (msg_p).eNB_ue_s1ap_id;
966
  ue_context_p = rrc_eNB_get_ue_context_from_s1ap_ids(instance, ue_initial_id, eNB_ue_s1ap_id);
knopp's avatar
knopp committed
967

968
969
970
971
972
  LOG_I(RRC, "[eNB %d] Received %s: ue_initial_id %d, eNB_ue_s1ap_id %d\n",
        instance,
        msg_name,
        ue_initial_id,
        eNB_ue_s1ap_id);
winckel's avatar
winckel committed
973

974
  if (ue_context_p == NULL) {
gauthier's avatar
gauthier committed
975
976

    MSC_LOG_RX_MESSAGE(
977
978
979
980
981
982
983
984
      MSC_RRC_ENB,
      MSC_S1AP_ENB,
      NULL,
      0,
      MSC_AS_TIME_FMT" DOWNLINK-NAS UE initial id %u eNB_ue_s1ap_id %u",
      0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
      ue_initial_id,
      eNB_ue_s1ap_id);
gauthier's avatar
gauthier committed
985

winckel's avatar
winckel committed
986
987
988
    /* Can not associate this message to an UE index, send a failure to S1AP and discard it! */
    MessageDef *msg_fail_p;

989
    LOG_W(RRC, "[eNB %d] In S1AP_DOWNLINK_NAS: unknown UE from S1AP ids (%d, %d)\n", instance, ue_initial_id, eNB_ue_s1ap_id);
winckel's avatar
winckel committed
990

winckel's avatar
winckel committed
991
    msg_fail_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_NAS_NON_DELIVERY_IND);
992
    S1AP_NAS_NON_DELIVERY_IND (msg_fail_p).eNB_ue_s1ap_id = eNB_ue_s1ap_id;
winckel's avatar
winckel committed
993
994
995
996
    S1AP_NAS_NON_DELIVERY_IND (msg_fail_p).nas_pdu.length = S1AP_DOWNLINK_NAS (msg_p).nas_pdu.length;
    S1AP_NAS_NON_DELIVERY_IND (msg_fail_p).nas_pdu.buffer = S1AP_DOWNLINK_NAS (msg_p).nas_pdu.buffer;

    // TODO add failure cause when defined!
winckel's avatar
winckel committed
997

gauthier's avatar
gauthier committed
998
999

    MSC_LOG_TX_MESSAGE(
1000
1001
1002
1003
1004
1005
1006
1007
      MSC_RRC_ENB,
      MSC_S1AP_ENB,
      (const char *)NULL,
      0,
      MSC_AS_TIME_FMT" S1AP_NAS_NON_DELIVERY_IND UE initial id %u eNB_ue_s1ap_id %u (ue ctxt !found)",
      0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
      ue_initial_id,
      eNB_ue_s1ap_id);
gauthier's avatar
gauthier committed
1008

winckel's avatar
winckel committed
1009
1010
    itti_send_msg_to_task (TASK_S1AP, instance, msg_fail_p);
    return (-1);
1011
  } else {
1012
    PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, ENB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0);
1013

knopp's avatar
knopp committed
1014
1015
1016
    srb_id = ue_context_p->ue_context.Srb2.Srb_info.Srb_id;
  

1017
    /* Is it the first income from S1AP ? */
1018
1019
    if (ue_context_p->ue_context.eNB_ue_s1ap_id == 0) {
      ue_context_p->ue_context.eNB_ue_s1ap_id = S1AP_DOWNLINK_NAS (msg_p).eNB_ue_s1ap_id;
1020
    }
gauthier's avatar
gauthier committed
1021
1022

    MSC_LOG_RX_MESSAGE(
1023
1024
1025
1026
1027
1028
1029
1030
      MSC_RRC_ENB,
      MSC_S1AP_ENB,
      (const char *)NULL,
      0,
      MSC_AS_TIME_FMT" DOWNLINK-NAS UE initial id %u eNB_ue_s1ap_id %u",
      0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
      ue_initial_id,
      S1AP_DOWNLINK_NAS (msg_p).eNB_ue_s1ap_id);
gauthier's avatar
gauthier committed
1031

1032
1033

    /* Create message for PDCP (DLInformationTransfer_t) */
1034
1035
1036
1037
    length = do_DLInformationTransfer (
               instance,
               &buffer,
               rrc_eNB_get_next_transaction_identifier (instance),
1038
1039
               S1AP_DOWNLINK_NAS (msg_p).nas_pdu.length,
               S1AP_DOWNLINK_NAS (msg_p).nas_pdu.buffer);
winckel's avatar
winckel committed
1040

1041
    LOG_DUMPMSG(RRC,DEBUG_RRC,buffer,length,"[MSG] RRC DL Information Transfer\n");
1042

1043
1044
1045
    /* 
     * switch UL or DL NAS message without RRC piggybacked to SRB2 if active. 
     */
winckel's avatar
winckel committed
1046
    /* Transfer data to PDCP */
1047
1048
    rrc_data_req (
		  &ctxt,
1049
		  srb_id,
1050
1051
1052
1053
1054
1055
		  *rrc_eNB_mui++,
		  SDU_CONFIRM_NO,
		  length,
		  buffer,
		  PDCP_TRANSMISSION_MODE_CONTROL);
    
winckel's avatar
winckel committed
1056
1057
1058
1059
1060
    return (0);
  }
}

/*------------------------------------------------------------------------------*/
1061
1062
int rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, const char *msg_name, instance_t instance)
{
1063
1064
  uint16_t                        ue_initial_id;