#if HAVE_CRT #define _CRTDBG_MAP_ALLOC #include <stdlib.h> #include <crtdbg.h> #endif //HAVE_CRT /* * Copyright (C) 2020, University of the Basque Country (UPV/EHU) * * Contact for licensing options: <licensing-mcpttclient(at)mcopenplatform(dot)com> * * This file is part of MCOP MCPTT Client * * This 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. * * This 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 this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /**@file tnet_mbms.c * @brief 3GPP MBMS */ #include "tnet_mbms.h" #include "../tnet_endianness.h" #include "tsk_string.h" #include "tsk_memory.h" #include "tsk_debug.h" #include <string.h> tnet_mbms_ctx_t* tnet_mbms_ctx_create() { return tsk_object_new(tnet_mbms_ctx_def_t); } tsk_bool_t tnet_mbms_check_network_tmgi(tnet_mbms_ctx_t* ctx) { if(ctx == tsk_null) return tsk_false; if (ctx->mbms_service_id == tsk_null || ctx->mcc == tsk_null || ctx->mnc == tsk_null || ctx->mbms_service_id_length != TNET_MBMS_SERVICE_ID_SIZE || ctx->mcc_length != TNET_MBMS_MCC_SIZE || ctx->mnc_length < 2 || ctx->mnc_length > 3) { return tsk_false; } //TODO: Need to check MBMS Service ID and MCC/MNC values in MBSFNAreaConfiguration and SystemInformationBlockType1 messages (LTE) return tsk_true; } tsk_bool_t tnet_mbms_parse_tmgi(tnet_mbms_ctx_t* ctx, uint8_t* tmgi, tsk_size_t tmgi_size) { tsk_bool_t ret = tsk_false; uint8_t* p; if(ctx == tsk_null) return tsk_false; if(tmgi_size != TNET_MBMS_TMGI_SIZE) return tsk_false; if(tmgi == tsk_null) return tsk_false; #if HAVE_CRT //Debug memory ctx->tmgi = (uint8_t*)calloc(TNET_MBMS_TMGI_SIZE, sizeof(uint8_t)); #else ctx->tmgi = (uint8_t*)tsk_calloc(TNET_MBMS_TMGI_SIZE, sizeof(uint8_t)); #endif //HAVE_CRT if(ctx->tmgi == tsk_null) goto bail; memcpy(ctx->tmgi, tmgi, tmgi_size); ctx->tmgi_size = TNET_MBMS_TMGI_SIZE; p = ctx->tmgi; #if HAVE_CRT //Debug memory ctx->mbms_service_id = (uint8_t*)calloc(TNET_MBMS_SERVICE_ID_SIZE, sizeof(uint8_t)); #else ctx->mbms_service_id = (uint8_t*)tsk_calloc(TNET_MBMS_SERVICE_ID_SIZE, sizeof(uint8_t)); #endif //HAVE_CRT if(ctx->mbms_service_id == tsk_null) { TSK_FREE(ctx->tmgi); ctx->tmgi_size = 0; goto bail; } memcpy(ctx->mbms_service_id, p, TNET_MBMS_SERVICE_ID_SIZE); ctx->mbms_service_id_length = TNET_MBMS_SERVICE_ID_SIZE; p += TNET_MBMS_SERVICE_ID_SIZE; #if HAVE_CRT //Debug memory ctx->mcc = (uint8_t*)calloc(TNET_MBMS_MCC_SIZE, sizeof(uint8_t)); #else ctx->mcc = (uint8_t*)tsk_calloc(TNET_MBMS_MCC_SIZE, sizeof(uint8_t)); #endif //HAVE_CRT if(ctx->mcc == tsk_null) { TSK_FREE(ctx->tmgi); ctx->tmgi_size = 0; TSK_FREE(ctx->mbms_service_id); ctx->mbms_service_id_length = 0; goto bail; } ctx->mcc[0] = p[0] & 0x0F; ctx->mcc[1] = (p[0] & 0xF0) >> 4; ctx->mcc[2] = p[1] & 0x0F; ctx->mcc_length = TNET_MBMS_MCC_SIZE; if(((p[1] & 0xF0) >> 4) == 0x0F) { ctx->mnc_length = 2; #if HAVE_CRT //Debug memory ctx->mnc = (uint8_t*)calloc(ctx->mnc_length, sizeof(uint8_t)); #else ctx->mnc = (uint8_t*)tsk_calloc(ctx->mnc_length, sizeof(uint8_t)); #endif //HAVE_CRT if(ctx->mnc == tsk_null) { TSK_FREE(ctx->tmgi); ctx->tmgi_size = 0; TSK_FREE(ctx->mbms_service_id); ctx->mbms_service_id_length = 0; TSK_FREE(ctx->mcc); ctx->mcc_length = 0; ctx->mnc_length = 0; goto bail; } ctx->mnc[0] = p[2] & 0x0F; ctx->mnc[1] = (p[2] & 0xF0) >> 4; } else { ctx->mnc_length = 3; #if HAVE_CRT //Debug memory ctx->mnc = (uint8_t*)calloc(ctx->mnc_length, sizeof(uint8_t)); #else ctx->mnc = (uint8_t*)tsk_calloc(ctx->mnc_length, sizeof(uint8_t)); #endif //HAVE_CRT if(ctx->mnc == tsk_null) goto bail; ctx->mnc[0] = p[2] & 0x0F; ctx->mnc[1] = (p[2] & 0xF0) >> 4; ctx->mnc[2] = (p[1] & 0xF0) >> 4; } ret = tsk_true; bail: return ret; } //================================================================================================= // [[MBMS CONTEXT]] object definition // static tsk_object_t* tnet_mbms_ctx_ctor(tsk_object_t * self, va_list * app) { tnet_mbms_ctx_t *ctx = self; if (ctx){ ctx->tmgi = tsk_null; ctx->tmgi_size = 0; ctx->mbms_service_id = tsk_null; ctx->mbms_service_id_length = 0; ctx->mcc = tsk_null; ctx->mcc_length = 0; ctx->mnc = tsk_null; ctx->mnc_length = 0; tsk_safeobj_init(ctx); } return self; } static tsk_object_t* tnet_mbms_ctx_dtor(tsk_object_t * self) { tnet_mbms_ctx_t *ctx = self; if (ctx){ tsk_safeobj_deinit(ctx); TSK_FREE(ctx->tmgi); TSK_FREE(ctx->mbms_service_id); TSK_FREE(ctx->mcc); TSK_FREE(ctx->mnc); } return self; } static const tsk_object_def_t tnet_mbms_ctx_def_s = { sizeof(tnet_mbms_ctx_t), tnet_mbms_ctx_ctor, tnet_mbms_ctx_dtor, tsk_null, }; const tsk_object_def_t *tnet_mbms_ctx_def_t = &tnet_mbms_ctx_def_s;