/******************************************************************************* 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. 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 . 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. *******************************************************************************/ #include #include #if defined(NAS_BUILT_IN_EPC) #include "assertions.h" #include "tree.h" #include "emmData.h" #include "nas_log.h" #include "security_types.h" static inline int emm_data_ctxt_compare_ueid(struct emm_data_context_s *p1, struct emm_data_context_s *p2); RB_PROTOTYPE(emm_data_context_map, emm_data_context_s, entries, emm_data_ctxt_compare_ueid); /* Generate functions used for the MAP */ RB_GENERATE(emm_data_context_map, emm_data_context_s, entries, emm_data_ctxt_compare_ueid); static inline int emm_data_ctxt_compare_ueid(struct emm_data_context_s *p1, struct emm_data_context_s *p2) { if (p1->ueid > p2->ueid) { return 1; } if (p1->ueid < p2->ueid) { return -1; } /* Matching reference -> return 0 */ return 0; } struct emm_data_context_s *emm_data_context_get( emm_data_t *emm_data, unsigned int _ueid) { struct emm_data_context_s reference; DevAssert(emm_data != NULL); DevCheck(_ueid > 0, _ueid, 0, 0); memset(&reference, 0, sizeof(struct emm_data_context_s)); reference.ueid = _ueid; return RB_FIND(emm_data_context_map, &emm_data->ctx_map, &reference); } struct emm_data_context_s *emm_data_context_remove( emm_data_t *emm_data, struct emm_data_context_s *elm) { LOG_TRACE(INFO, "EMM-CTX - Remove in context %p UE id "NAS_UE_ID_FMT" ", elm, elm->ueid); return RB_REMOVE(emm_data_context_map, &emm_data->ctx_map, elm); } void emm_data_context_add(emm_data_t *emm_data, struct emm_data_context_s *elm) { LOG_TRACE(INFO, "EMM-CTX - Add in context %p UE id "NAS_UE_ID_FMT" ", elm, elm->ueid); RB_INSERT(emm_data_context_map, &emm_data->ctx_map, elm); } void emm_data_context_dump(struct emm_data_context_s *elm_pP) { if (elm_pP != NULL) { char imsi_str[16]; char guti_str[22]; int k, size, remaining_size; char key_string[KASME_LENGTH_OCTETS*2]; LOG_TRACE(INFO, "EMM-CTX: ue id: "NAS_UE_ID_FMT" (UE identifier)", elm_pP->ueid); LOG_TRACE(INFO, " is_dynamic: %u (Dynamically allocated context indicator)", elm_pP->is_dynamic); LOG_TRACE(INFO, " is_attached: %u (Attachment indicator)", elm_pP->is_attached); LOG_TRACE(INFO, " is_emergency: %u (Emergency bearer services indicator)", elm_pP->is_emergency); NAS_IMSI2STR(elm_pP->imsi, imsi_str, 16); LOG_TRACE(INFO, " imsi: %s (The IMSI provided by the UE or the MME)", imsi_str); LOG_TRACE(INFO, " imei: TODO (The IMEI provided by the UE)"); LOG_TRACE(INFO, " guti_is_new: %u (New GUTI indicator)", elm_pP->guti_is_new); GUTI2STR(elm_pP->guti, guti_str, 22); LOG_TRACE(INFO, " guti: %s (The GUTI assigned to the UE)", guti_str); GUTI2STR(elm_pP->old_guti, guti_str, 22); LOG_TRACE(INFO, " old_guti: %s (The old GUTI)", guti_str); LOG_TRACE(INFO, " n_tacs: %u (Number of consecutive tracking areas the UE is registered to)", elm_pP->n_tacs); LOG_TRACE(INFO, " tac: 0x%04x (Code of the first tracking area the UE is registered to)", elm_pP->n_tacs); LOG_TRACE(INFO, " ksi: %u (Security key set identifier provided by the UE)", elm_pP->ksi); LOG_TRACE(INFO, " auth_vector: (EPS authentication vector)"); LOG_TRACE(INFO, " kasme: "KASME_FORMAT""KASME_FORMAT, KASME_DISPLAY_1(elm_pP->vector.kasme), KASME_DISPLAY_2(elm_pP->vector.kasme)); LOG_TRACE(INFO, " rand: "RAND_FORMAT, RAND_DISPLAY(elm_pP->vector.rand)); LOG_TRACE(INFO, " autn: "AUTN_FORMAT, AUTN_DISPLAY(elm_pP->vector.autn)); for (k = 0; k < XRES_LENGTH_MAX; k++) {sprintf(&key_string[k * 3], "%02x,", elm_pP->vector.xres[k]);} key_string[k * 3 - 1] = '\0'; LOG_TRACE(INFO, " xres: %s\n", key_string); if (elm_pP->security != NULL) { LOG_TRACE(INFO, " security context: (Current EPS NAS security context)"); LOG_TRACE(INFO, " type: %s (Type of security context)", (elm_pP->security->type == EMM_KSI_NOT_AVAILABLE)?"KSI_NOT_AVAILABLE":(elm_pP->security->type == EMM_KSI_NATIVE)?"KSI_NATIVE":"KSI_MAPPED"); LOG_TRACE(INFO, " eksi: %u (NAS key set identifier for E-UTRAN)", elm_pP->security->eksi); if (elm_pP->security->kasme.length > 0) { size = 0; size = 0;remaining_size=KASME_LENGTH_OCTETS*2; for (k = 0; k < elm_pP->security->kasme.length; k++) { size +=snprintf(&key_string[size], remaining_size, "0x%x ", elm_pP->security->kasme.value[k]); remaining_size -= size; } } else { size +=snprintf(&key_string[0], remaining_size, "None"); } LOG_TRACE(INFO, " kasme: %s (ASME security key (native context))", key_string); if (elm_pP->security->knas_enc.length > 0) { size = 0; size = 0;remaining_size=KASME_LENGTH_OCTETS*2; for (k = 0; k < elm_pP->security->knas_enc.length; k++) { size +=snprintf(&key_string[size], remaining_size, "0x%x ", elm_pP->security->knas_enc.value[k]); remaining_size -= size; } } else { size +=snprintf(&key_string[0], remaining_size, "None"); } LOG_TRACE(INFO, " knas_enc: %s (NAS cyphering key)", key_string); if (elm_pP->security->knas_int.length > 0) { size = 0;remaining_size=KASME_LENGTH_OCTETS*2; for (k = 0; k < elm_pP->security->knas_int.length; k++) { size +=snprintf(&key_string[size], remaining_size, "0x%x ", elm_pP->security->knas_int.value[k]); remaining_size -= size; } } else { size +=snprintf(&key_string[0], remaining_size, "None"); } LOG_TRACE(INFO, " knas_int: %s (NAS integrity key)", key_string); LOG_TRACE(INFO, " dl_count.overflow: %u ", elm_pP->security->dl_count.overflow); LOG_TRACE(INFO, " dl_count.seq_num: %u ", elm_pP->security->dl_count.seq_num); LOG_TRACE(INFO, " ul_count.overflow: %u ", elm_pP->security->ul_count.overflow); LOG_TRACE(INFO, " ul_count.seq_num: %u ", elm_pP->security->ul_count.seq_num); LOG_TRACE(INFO, " TODO capability"); LOG_TRACE(INFO, " selected_algorithms.encryption: %x ", elm_pP->security->selected_algorithms.encryption); LOG_TRACE(INFO, " selected_algorithms.integrity: %x ", elm_pP->security->selected_algorithms.integrity); } else { LOG_TRACE(INFO, " No security context"); } LOG_TRACE(INFO, " _emm_fsm_status %u ", elm_pP->_emm_fsm_status); LOG_TRACE(INFO, " TODO esm_data_ctx"); } } void emm_data_context_dump_all(void) { struct emm_data_context_s *elm_p = NULL; LOG_TRACE(INFO, "EMM-CTX - Dump all contexts:"); RB_FOREACH(elm_p, emm_data_context_map,&_emm_data.ctx_map) { emm_data_context_dump(elm_p); } } #endif