/* * 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.1 (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 */ #include #include #include #include "TLVEncoder.h" #include "TLVDecoder.h" #include "EpsMobileIdentity.h" static int decode_guti_eps_mobile_identity(GutiEpsMobileIdentity_t *guti, uint8_t *buffer); static int decode_imsi_eps_mobile_identity(ImsiEpsMobileIdentity_t *imsi, uint8_t *buffer); static int decode_imei_eps_mobile_identity(ImeiEpsMobileIdentity_t *imei, uint8_t *buffer); static int encode_guti_eps_mobile_identity(GutiEpsMobileIdentity_t *guti, uint8_t *buffer); static int encode_imsi_eps_mobile_identity(ImsiEpsMobileIdentity_t *imsi, uint8_t *buffer); static int encode_imei_eps_mobile_identity(ImeiEpsMobileIdentity_t *imei, uint8_t *buffer); int decode_eps_mobile_identity(EpsMobileIdentity *epsmobileidentity, uint8_t iei, uint8_t *buffer, uint32_t len) { int decoded_rc = TLV_DECODE_VALUE_DOESNT_MATCH; int decoded = 0; uint8_t ielen = 0; if (iei > 0) { CHECK_IEI_DECODER(iei, *buffer); decoded++; } ielen = *(buffer + decoded); decoded++; CHECK_LENGTH_DECODER(len - decoded, ielen); uint8_t typeofidentity = *(buffer + decoded) & 0x7; if (typeofidentity == EPS_MOBILE_IDENTITY_IMSI) { decoded_rc = decode_imsi_eps_mobile_identity(&epsmobileidentity->imsi, buffer + decoded); } else if (typeofidentity == EPS_MOBILE_IDENTITY_GUTI) { decoded_rc = decode_guti_eps_mobile_identity(&epsmobileidentity->guti, buffer + decoded); } else if (typeofidentity == EPS_MOBILE_IDENTITY_IMEI) { decoded_rc = decode_imei_eps_mobile_identity(&epsmobileidentity->imei, buffer + decoded); } if (decoded_rc < 0) { return decoded_rc; } #if defined (NAS_DEBUG) dump_eps_mobile_identity_xml(epsmobileidentity, iei); #endif return (decoded + decoded_rc); } int encode_eps_mobile_identity(EpsMobileIdentity *epsmobileidentity, uint8_t iei, uint8_t *buffer, uint32_t len) { uint8_t *lenPtr; int encoded_rc = TLV_ENCODE_VALUE_DOESNT_MATCH; uint32_t encoded = 0; /* Checking IEI and pointer */ CHECK_PDU_POINTER_AND_LENGTH_ENCODER(buffer, EPS_MOBILE_IDENTITY_MINIMUM_LENGTH, len); #if defined (NAS_DEBUG) dump_eps_mobile_identity_xml(epsmobileidentity, iei); #endif if (iei > 0) { *buffer = iei; encoded++; } lenPtr = (buffer + encoded); encoded ++; if (epsmobileidentity->imsi.typeofidentity == EPS_MOBILE_IDENTITY_IMSI) { encoded_rc = encode_imsi_eps_mobile_identity(&epsmobileidentity->imsi, buffer + encoded); } else if (epsmobileidentity->guti.typeofidentity == EPS_MOBILE_IDENTITY_GUTI) { encoded_rc = encode_guti_eps_mobile_identity(&epsmobileidentity->guti, buffer + encoded); } else if (epsmobileidentity->imei.typeofidentity == EPS_MOBILE_IDENTITY_IMEI) { encoded_rc = encode_imei_eps_mobile_identity(&epsmobileidentity->imei, buffer + encoded); } if (encoded_rc < 0) { return encoded_rc; } *lenPtr = encoded + encoded_rc - 1 - ((iei > 0) ? 1 : 0); return (encoded + encoded_rc); } void dump_eps_mobile_identity_xml(EpsMobileIdentity *epsmobileidentity, uint8_t iei) { printf("\n"); if (iei > 0) /* Don't display IEI if = 0 */ printf(" 0x%X\n", iei); if (epsmobileidentity->imsi.typeofidentity == EPS_MOBILE_IDENTITY_IMSI) { ImsiEpsMobileIdentity_t* imsi = &epsmobileidentity->imsi; printf(" %u\n", imsi->oddeven); printf(" IMSI\n"); printf(" %u\n", imsi->digit1); printf(" %u\n", imsi->digit2); printf(" %u\n", imsi->digit3); printf(" %u\n", imsi->digit4); printf(" %u\n", imsi->digit5); printf(" %u\n", imsi->digit6); printf(" %u\n", imsi->digit7); printf(" %u\n", imsi->digit8); printf(" %u\n", imsi->digit9); printf(" %u\n", imsi->digit10); printf(" %u\n", imsi->digit11); printf(" %u\n", imsi->digit12); printf(" %u\n", imsi->digit13); printf(" %u\n", imsi->digit14); printf(" %u\n", imsi->digit15); } else if (epsmobileidentity->guti.typeofidentity == EPS_MOBILE_IDENTITY_GUTI) { GutiEpsMobileIdentity_t* guti = &epsmobileidentity->guti; printf(" %u\n", guti->oddeven); printf(" GUTI\n"); printf(" %u\n", guti->mccdigit1); printf(" %u\n", guti->mccdigit2); printf(" %u\n", guti->mccdigit3); printf(" %u\n", guti->mncdigit1); printf(" %u\n", guti->mncdigit2); printf(" %u\n", guti->mncdigit3); printf(" %u\n", guti->mmegroupid); printf(" %u\n", guti->mmecode); printf(" %u\n", guti->mtmsi); } else if (epsmobileidentity->imei.typeofidentity == EPS_MOBILE_IDENTITY_IMEI) { ImeiEpsMobileIdentity_t* imei = &epsmobileidentity->imei; printf(" %u\n", imei->oddeven); printf(" IMEI\n"); printf(" %u\n", imei->digit1); printf(" %u\n", imei->digit2); printf(" %u\n", imei->digit3); printf(" %u\n", imei->digit4); printf(" %u\n", imei->digit5); printf(" %u\n", imei->digit6); printf(" %u\n", imei->digit7); printf(" %u\n", imei->digit8); printf(" %u\n", imei->digit9); printf(" %u\n", imei->digit10); printf(" %u\n", imei->digit11); printf(" %u\n", imei->digit12); printf(" %u\n", imei->digit13); printf(" %u\n", imei->digit14); printf(" %u\n", imei->digit15); } else { printf(" Wrong type of EPS mobile identity (%u)\n", epsmobileidentity->guti.typeofidentity); } printf("\n"); } static int decode_guti_eps_mobile_identity(GutiEpsMobileIdentity_t *guti, uint8_t *buffer) { int decoded = 0; guti->spare = (*(buffer + decoded) >> 4) & 0xf; /* * For the GUTI, bits 5 to 8 of octet 3 are coded as "1111" */ if (guti->spare != 0xf) { return (TLV_ENCODE_VALUE_DOESNT_MATCH); } guti->oddeven = (*(buffer + decoded) >> 3) & 0x1; guti->typeofidentity = *(buffer + decoded) & 0x7; if (guti->typeofidentity != EPS_MOBILE_IDENTITY_GUTI) { return (TLV_ENCODE_VALUE_DOESNT_MATCH); } decoded++; guti->mccdigit2 = (*(buffer + decoded) >> 4) & 0xf; guti->mccdigit1 = *(buffer + decoded) & 0xf; decoded++; guti->mncdigit3 = (*(buffer + decoded) >> 4) & 0xf; guti->mccdigit3 = *(buffer + decoded) & 0xf; decoded++; guti->mncdigit2 = (*(buffer + decoded) >> 4) & 0xf; guti->mncdigit1 = *(buffer + decoded) & 0xf; decoded++; //IES_DECODE_U16(guti->mmegroupid, *(buffer + decoded)); IES_DECODE_U16(buffer, decoded, guti->mmegroupid); guti->mmecode = *(buffer + decoded); decoded++; //IES_DECODE_U32(guti->mtmsi, *(buffer + decoded)); IES_DECODE_U32(buffer, decoded, guti->mtmsi); return decoded; } static int decode_imsi_eps_mobile_identity(ImsiEpsMobileIdentity_t *imsi, uint8_t *buffer) { int decoded = 0; imsi->typeofidentity = *(buffer + decoded) & 0x7; if (imsi->typeofidentity != EPS_MOBILE_IDENTITY_IMSI) { return (TLV_ENCODE_VALUE_DOESNT_MATCH); } imsi->oddeven = (*(buffer + decoded) >> 3) & 0x1; imsi->digit1 = (*(buffer + decoded) >> 4) & 0xf; decoded++; imsi->digit2 = *(buffer + decoded) & 0xf; imsi->digit3 = (*(buffer + decoded) >> 4) & 0xf; decoded++; imsi->digit4 = *(buffer + decoded) & 0xf; imsi->digit5 = (*(buffer + decoded) >> 4) & 0xf; decoded++; imsi->digit6 = *(buffer + decoded) & 0xf; imsi->digit7 = (*(buffer + decoded) >> 4) & 0xf; decoded++; imsi->digit8 = *(buffer + decoded) & 0xf; imsi->digit9 = (*(buffer + decoded) >> 4) & 0xf; decoded++; imsi->digit10 = *(buffer + decoded) & 0xf; imsi->digit11 = (*(buffer + decoded) >> 4) & 0xf; decoded++; imsi->digit12 = *(buffer + decoded) & 0xf; imsi->digit13 = (*(buffer + decoded) >> 4) & 0xf; decoded++; imsi->digit14 = *(buffer + decoded) & 0xf; imsi->digit15 = (*(buffer + decoded) >> 4) & 0xf; /* * IMSI is coded using BCD coding. If the number of identity digits is * even then bits 5 to 8 of the last octet shall be filled with an end * mark coded as "1111". */ if ((imsi->oddeven == EPS_MOBILE_IDENTITY_EVEN) && (imsi->digit15 != 0x0f)) { return (TLV_ENCODE_VALUE_DOESNT_MATCH); } decoded++; return decoded; } static int decode_imei_eps_mobile_identity(ImeiEpsMobileIdentity_t *imei, uint8_t *buffer) { int decoded = 0; imei->typeofidentity = *(buffer + decoded) & 0x7; if (imei->typeofidentity != EPS_MOBILE_IDENTITY_IMEI) { return (TLV_ENCODE_VALUE_DOESNT_MATCH); } imei->oddeven = (*(buffer + decoded) >> 3) & 0x1; imei->digit1 = (*(buffer + decoded) >> 4) & 0xf; decoded++; imei->digit2 = *(buffer + decoded) & 0xf; imei->digit3 = (*(buffer + decoded) >> 4) & 0xf; decoded++; imei->digit4 = *(buffer + decoded) & 0xf; imei->digit5 = (*(buffer + decoded) >> 4) & 0xf; decoded++; imei->digit6 = *(buffer + decoded) & 0xf; imei->digit7 = (*(buffer + decoded) >> 4) & 0xf; decoded++; imei->digit8 = *(buffer + decoded) & 0xf; imei->digit9 = (*(buffer + decoded) >> 4) & 0xf; decoded++; imei->digit10 = *(buffer + decoded) & 0xf; imei->digit11 = (*(buffer + decoded) >> 4) & 0xf; decoded++; imei->digit12 = *(buffer + decoded) & 0xf; imei->digit13 = (*(buffer + decoded) >> 4) & 0xf; decoded++; imei->digit14 = *(buffer + decoded) & 0xf; imei->digit15 = (*(buffer + decoded) >> 4) & 0xf; decoded++; return decoded; } static int encode_guti_eps_mobile_identity(GutiEpsMobileIdentity_t *guti, uint8_t *buffer) { uint32_t encoded = 0; *(buffer + encoded) = 0xf0 | ((guti->oddeven & 0x1) << 3) | (guti->typeofidentity & 0x7); encoded++; *(buffer + encoded) = 0x00 | ((guti->mccdigit2 & 0xf) << 4) | (guti->mccdigit1 & 0xf); encoded++; *(buffer + encoded) = 0x00 | ((guti->mncdigit3 & 0xf) << 4) | (guti->mccdigit3 & 0xf); encoded++; *(buffer + encoded) = 0x00 | ((guti->mncdigit2 & 0xf) << 4) | (guti->mncdigit1 & 0xf); encoded++; IES_ENCODE_U16(buffer, encoded, guti->mmegroupid); *(buffer + encoded) = guti->mmecode; encoded++; IES_ENCODE_U32(buffer, encoded, guti->mtmsi); return encoded; } static int encode_imsi_eps_mobile_identity(ImsiEpsMobileIdentity_t *imsi, uint8_t *buffer) { uint32_t encoded = 0; *(buffer + encoded) = 0x00 | (imsi->digit1 << 4) | (imsi->oddeven << 3) | (imsi->typeofidentity); encoded++; *(buffer + encoded) = 0x00 | (imsi->digit3 << 4) | imsi->digit2; encoded++; *(buffer + encoded) = 0x00 | (imsi->digit5 << 4) | imsi->digit4; encoded++; *(buffer + encoded) = 0x00 | (imsi->digit7 << 4) | imsi->digit6; encoded++; *(buffer + encoded) = 0x00 | (imsi->digit9 << 4) | imsi->digit8; encoded++; *(buffer + encoded) = 0x00 | (imsi->digit11 << 4) | imsi->digit10; encoded++; *(buffer + encoded) = 0x00 | (imsi->digit13 << 4) | imsi->digit12; encoded++; if (imsi->oddeven != EPS_MOBILE_IDENTITY_EVEN) { *(buffer + encoded) = 0x00 | (imsi->digit15 << 4) | imsi->digit14; } else { *(buffer + encoded) = 0xf0 | imsi->digit14; } encoded++; return encoded; } static int encode_imei_eps_mobile_identity(ImeiEpsMobileIdentity_t *imei, uint8_t *buffer) { uint32_t encoded = 0; *(buffer + encoded) = 0x00 | (imei->digit1 << 4) | (imei->oddeven << 3) | (imei->typeofidentity); encoded++; *(buffer + encoded) = 0x00 | (imei->digit3 << 4) | imei->digit2; encoded++; *(buffer + encoded) = 0x00 | (imei->digit5 << 4) | imei->digit4; encoded++; *(buffer + encoded) = 0x00 | (imei->digit7 << 4) | imei->digit6; encoded++; *(buffer + encoded) = 0x00 | (imei->digit9 << 4) | imei->digit8; encoded++; *(buffer + encoded) = 0x00 | (imei->digit11 << 4) | imei->digit10; encoded++; *(buffer + encoded) = 0x00 | (imei->digit13 << 4) | imei->digit12; encoded++; *(buffer + encoded) = 0x00 | (imei->digit15 << 4) | imei->digit14; encoded++; return encoded; }