/*******************************************************************************
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.
*******************************************************************************/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include
#include
#include
#include
#include
#include
#include
#include /* To provide inet_addr */
#include "assertions.h"
#include "mme_config.h"
#include "spgw_config.h"
#include "intertask_interface_conf.h"
mme_config_t mme_config;
int mme_config_find_mnc_length(const char mcc_digit1P,
const char mcc_digit2P,
const char mcc_digit3P,
const char mnc_digit1P,
const char mnc_digit2P,
const char mnc_digit3P) {
uint16_t mcc = 100*mcc_digit1P + 10*mcc_digit2P + mcc_digit3P;
uint16_t mnc3= 100*mnc_digit1P + 10*mnc_digit2P + mnc_digit3P;
uint16_t mnc2= 10*mnc_digit1P + mnc_digit2P;
int plmn_index = 0;
AssertFatal((mcc_digit1P >= 0) && (mcc_digit1P <= 9)
&& (mcc_digit2P >= 0) && (mcc_digit2P <= 9)
&& (mcc_digit3P >= 0) && (mcc_digit3P <= 9) ,
"BAD MCC PARAMETER (%d%d%d)!\n",
mcc_digit1P, mcc_digit2P, mcc_digit3P);
AssertFatal((mnc_digit2P >= 0) && (mnc_digit2P <= 9)
&& (mnc_digit1P >= 0) && (mnc_digit1P <= 9) ,
"BAD MNC PARAMETER (%d.%d.%d)!\n",
mnc_digit1P, mnc_digit2P, mnc_digit3P);
while (plmn_index < mme_config.gummei.nb_plmns) {
if (mme_config.gummei.plmn_mcc[plmn_index] == mcc) {
if ((mme_config.gummei.plmn_mnc[plmn_index] == mnc2) &&
(mme_config.gummei.plmn_mnc_len[plmn_index] == 2)) {
return 2;
} else if ((mme_config.gummei.plmn_mnc[plmn_index] == mnc3) &&
(mme_config.gummei.plmn_mnc_len[plmn_index] == 3)) {
return 3;
}
}
plmn_index += 1;
}
return 0;
}
static
void mme_config_init(mme_config_t *mme_config_p)
{
memset(mme_config_p, 0, sizeof(mme_config_t));
pthread_rwlock_init(&mme_config_p->rw_lock, NULL);
mme_config_p->verbosity_level = 0;
mme_config_p->config_file = NULL;
mme_config_p->max_eNBs = MAX_NUMBER_OF_ENB;
mme_config_p->max_ues = MAX_NUMBER_OF_UE;
mme_config_p->emergency_attach_supported = 0;
mme_config_p->unauthenticated_imsi_supported = 0;
/* Timer configuration */
mme_config_p->gtpv1u_config.port_number = GTPV1_U_PORT_NUMBER;
mme_config_p->s1ap_config.port_number = S1AP_PORT_NUMBER;
/* IP configuration */
mme_config_p->ipv4.sgw_ip_address_for_S1u_S12_S4_up = inet_addr(DEFAULT_SGW_IP_ADDRESS_FOR_S1U_S12_S4_UP);
mme_config_p->ipv4.mme_interface_name_for_S1_MME = DEFAULT_MME_INTERFACE_NAME_FOR_S1_MME;
mme_config_p->ipv4.mme_ip_address_for_S1_MME = inet_addr(DEFAULT_MME_IP_ADDRESS_FOR_S1_MME);
mme_config_p->ipv4.mme_interface_name_for_S11 = DEFAULT_MME_INTERFACE_NAME_FOR_S11;
mme_config_p->ipv4.mme_ip_address_for_S11 = inet_addr(DEFAULT_MME_IP_ADDRESS_FOR_S11);
mme_config_p->ipv4.sgw_ip_address_for_S11 = inet_addr(DEFAULT_SGW_IP_ADDRESS_FOR_S11);
mme_config_p->s6a_config.conf_file = S6A_CONF_FILE;
mme_config_p->itti_config.queue_size = ITTI_QUEUE_MAX_ELEMENTS;
mme_config_p->itti_config.log_file = NULL;
mme_config_p->sctp_config.in_streams = SCTP_IN_STREAMS;
mme_config_p->sctp_config.out_streams = SCTP_OUT_STREAMS;
mme_config_p->relative_capacity = RELATIVE_CAPACITY;
mme_config_p->mme_statistic_timer = MME_STATISTIC_TIMER_S;
mme_config_p->gummei.nb_mme_gid = 1;
mme_config_p->gummei.mme_gid = calloc(1, sizeof(*mme_config_p->gummei.mme_gid));
mme_config_p->gummei.mme_gid[0] = MMEGID;
mme_config_p->gummei.nb_mmec = 1;
mme_config_p->gummei.mmec = calloc(1, sizeof(*mme_config_p->gummei.mmec));
mme_config_p->gummei.mmec[0] = MMEC;
/* Set the TAI */
mme_config_p->gummei.nb_plmns = 1;
mme_config_p->gummei.plmn_mcc = calloc(1, sizeof(*mme_config_p->gummei.plmn_mcc));
mme_config_p->gummei.plmn_mnc = calloc(1, sizeof(*mme_config_p->gummei.plmn_mnc));
mme_config_p->gummei.plmn_tac = calloc(1, sizeof(*mme_config_p->gummei.plmn_tac));
mme_config_p->gummei.plmn_mcc[0] = PLMN_MCC;
mme_config_p->gummei.plmn_mnc[0] = PLMN_MNC;
mme_config_p->gummei.plmn_tac[0] = PLMN_TAC;
mme_config_p->s1ap_config.outcome_drop_timer_sec = S1AP_OUTCOME_TIMER_DEFAULT;
}
int mme_system(char *command_pP, int abort_on_errorP) {
int ret = -1;
if (command_pP) {
fprintf(stdout, "system command: %s\n",command_pP);
ret = system(command_pP);
if (ret < 0) {
fprintf(stderr, "ERROR in system command %s: %d\n",
command_pP,ret);
if (abort_on_errorP) {
exit(-1); // may be not exit
}
}
}
return ret;
}
static int config_parse_file(mme_config_t *mme_config_p)
{
config_t cfg;
config_setting_t *setting_mme = NULL;
config_setting_t *setting = NULL;
config_setting_t *subsetting = NULL;
config_setting_t *sub2setting = NULL;
long int alongint;
int i, num;
char *astring = NULL;
char *address = NULL;
char *cidr = NULL;
const char* tac = NULL;
const char* mcc = NULL;
const char* mnc = NULL;
char *sgw_ip_address_for_S1u_S12_S4_up = NULL;
char *mme_interface_name_for_S1_MME = NULL;
char *mme_ip_address_for_S1_MME = NULL;
char *mme_interface_name_for_S11 = NULL;
char *mme_ip_address_for_S11 = NULL;
char *sgw_ip_address_for_S11 = NULL;
#if defined (ENABLE_USE_GTPU_IN_KERNEL)
char system_cmd[256];
#endif
config_init(&cfg);
if(mme_config_p->config_file != NULL)
{
/* Read the file. If there is an error, report it and exit. */
if(! config_read_file(&cfg, mme_config_p->config_file))
{
fprintf(stdout, "ERROR: %s:%d - %s\n", mme_config_p->config_file, config_error_line(&cfg), config_error_text(&cfg));
config_destroy(&cfg);
AssertFatal (1 == 0, "Failed to parse MME configuration file %s!\n", mme_config_p->config_file);
}
}
else
{
fprintf(stdout, "ERROR No MME configuration file provided!\n");
config_destroy(&cfg);
AssertFatal (0, "No MME configuration file provided!\n");
}
setting_mme = config_lookup(&cfg, MME_CONFIG_STRING_MME_CONFIG);
if(setting_mme != NULL) {
// GENERAL MME SETTINGS
if( (config_setting_lookup_string( setting_mme, MME_CONFIG_STRING_REALM, (const char **)&astring) )) {
mme_config_p->realm = strdup(astring);
mme_config_p->realm_length = strlen(mme_config_p->realm);
}
if( (config_setting_lookup_int( setting_mme, MME_CONFIG_STRING_MAXENB, &alongint) )) {
mme_config_p->max_eNBs = (uint32_t)alongint;
}
if( (config_setting_lookup_int( setting_mme, MME_CONFIG_STRING_MAXUE, &alongint) )) {
mme_config_p->max_ues = (uint32_t)alongint;
}
if( (config_setting_lookup_int( setting_mme, MME_CONFIG_STRING_RELATIVE_CAPACITY, &alongint) )) {
mme_config_p->relative_capacity = (uint8_t)alongint;
}
if( (config_setting_lookup_int( setting_mme, MME_CONFIG_STRING_STATISTIC_TIMER, &alongint) )) {
mme_config_p->mme_statistic_timer = (uint32_t)alongint;
}
if( (config_setting_lookup_string( setting_mme, MME_CONFIG_STRING_EMERGENCY_ATTACH_SUPPORTED, (const char **)&astring) )) {
if (strcasecmp(astring , "yes") == 0)
mme_config_p->emergency_attach_supported = 1;
else
mme_config_p->emergency_attach_supported = 0;
}
if( (config_setting_lookup_string( setting_mme, MME_CONFIG_STRING_UNAUTHENTICATED_IMSI_SUPPORTED, (const char **)&astring) )) {
if (strcasecmp(astring , "yes") == 0)
mme_config_p->unauthenticated_imsi_supported = 1;
else
mme_config_p->unauthenticated_imsi_supported = 0;
}
if( (config_setting_lookup_string( setting_mme, MME_CONFIG_STRING_ASN1_VERBOSITY, (const char **)&astring) )) {
if (strcasecmp(astring , MME_CONFIG_STRING_ASN1_VERBOSITY_NONE) == 0)
mme_config_p->verbosity_level = 0;
else if (strcasecmp(astring , MME_CONFIG_STRING_ASN1_VERBOSITY_ANNOYING) == 0)
mme_config_p->verbosity_level = 2;
else if (strcasecmp(astring , MME_CONFIG_STRING_ASN1_VERBOSITY_INFO) == 0)
mme_config_p->verbosity_level = 1;
else
mme_config_p->verbosity_level = 0;
}
// ITTI SETTING
setting = config_setting_get_member (setting_mme, MME_CONFIG_STRING_INTERTASK_INTERFACE_CONFIG);
if (setting != NULL) {
if( (config_setting_lookup_int( setting, MME_CONFIG_STRING_INTERTASK_INTERFACE_QUEUE_SIZE, &alongint) )) {
mme_config_p->itti_config.queue_size = (uint32_t)alongint;
}
}
// S6A SETTING
setting = config_setting_get_member (setting_mme, MME_CONFIG_STRING_S6A_CONFIG);
if (setting != NULL) {
if( (config_setting_lookup_string( setting, MME_CONFIG_STRING_S6A_CONF_FILE_PATH, (const char **)&astring) )) {
if (astring != NULL)
mme_config_p->s6a_config.conf_file = strdup(astring);
}
}
// SCTP SETTING
setting = config_setting_get_member (setting_mme, MME_CONFIG_STRING_SCTP_CONFIG);
if (setting != NULL) {
if( (config_setting_lookup_int( setting, MME_CONFIG_STRING_SCTP_INSTREAMS, &alongint) )) {
mme_config_p->sctp_config.in_streams = (uint16_t)alongint;
}
if( (config_setting_lookup_int( setting, MME_CONFIG_STRING_SCTP_OUTSTREAMS, &alongint) )) {
mme_config_p->sctp_config.out_streams = (uint16_t)alongint;
}
}
// S1AP SETTING
setting = config_setting_get_member (setting_mme, MME_CONFIG_STRING_S1AP_CONFIG);
if (setting != NULL) {
if( (config_setting_lookup_int( setting, MME_CONFIG_STRING_S1AP_OUTCOME_TIMER, &alongint) )) {
mme_config_p->s1ap_config.outcome_drop_timer_sec = (uint8_t)alongint;
}
if( (config_setting_lookup_int( setting, MME_CONFIG_STRING_S1AP_PORT, &alongint) )) {
mme_config_p->s1ap_config.port_number = (uint16_t)alongint;
}
}
// GUMMEI SETTING
setting = config_setting_get_member (setting_mme, MME_CONFIG_STRING_GUMMEI_CONFIG);
if (setting != NULL) {
subsetting = config_setting_get_member (setting, MME_CONFIG_STRING_MME_CODE);
if (subsetting != NULL) {
num = config_setting_length(subsetting);
if (mme_config_p->gummei.nb_mmec != num) {
if (mme_config_p->gummei.mmec != NULL) {
free(mme_config_p->gummei.mmec);
}
mme_config_p->gummei.mmec = calloc(num, sizeof(*mme_config_p->gummei.mmec));
}
mme_config_p->gummei.nb_mmec = num;
for (i = 0; i < num; i++) {
mme_config_p->gummei.mmec[i] = config_setting_get_int_elem(subsetting, i);
}
}
subsetting = config_setting_get_member (setting, MME_CONFIG_STRING_MME_GID);
if (subsetting != NULL) {
num = config_setting_length(subsetting);
if (mme_config_p->gummei.nb_mme_gid != num) {
if (mme_config_p->gummei.mme_gid != NULL) {
free(mme_config_p->gummei.mme_gid);
}
mme_config_p->gummei.mme_gid = calloc(num, sizeof(*mme_config_p->gummei.mme_gid));
}
mme_config_p->gummei.nb_mme_gid = num;
for (i = 0; i < num; i++) {
mme_config_p->gummei.mme_gid[i] = config_setting_get_int_elem(subsetting, i);
}
}
subsetting = config_setting_get_member (setting, MME_CONFIG_STRING_PLMN);
if (subsetting != NULL) {
num = config_setting_length(subsetting);
if (mme_config_p->gummei.nb_plmns != num) {
if (mme_config_p->gummei.plmn_mcc != NULL) free(mme_config_p->gummei.plmn_mcc);
if (mme_config_p->gummei.plmn_mnc != NULL) free(mme_config_p->gummei.plmn_mnc);
if (mme_config_p->gummei.plmn_mnc_len != NULL) free(mme_config_p->gummei.plmn_mnc_len);
if (mme_config_p->gummei.plmn_tac != NULL) free(mme_config_p->gummei.plmn_tac);
mme_config_p->gummei.plmn_mcc = calloc(num, sizeof(*mme_config_p->gummei.plmn_mcc));
mme_config_p->gummei.plmn_mnc = calloc(num, sizeof(*mme_config_p->gummei.plmn_mnc));
mme_config_p->gummei.plmn_mnc_len = calloc(num, sizeof(*mme_config_p->gummei.plmn_mnc_len));
mme_config_p->gummei.plmn_tac = calloc(num, sizeof(*mme_config_p->gummei.plmn_tac));
}
mme_config_p->gummei.nb_plmns = num;
for (i = 0; i < num; i++) {
sub2setting = config_setting_get_elem(subsetting, i);
if (sub2setting != NULL) {
if( (config_setting_lookup_string( sub2setting, MME_CONFIG_STRING_MCC, &mcc) )) {
mme_config_p->gummei.plmn_mcc[i] = (uint16_t)atoi(mcc);
}
if( (config_setting_lookup_string( sub2setting, MME_CONFIG_STRING_MNC, &mnc) )) {
mme_config_p->gummei.plmn_mnc[i] = (uint16_t)atoi(mnc);
mme_config_p->gummei.plmn_mnc_len[i] = strlen(mnc);
AssertFatal((mme_config_p->gummei.plmn_mnc_len[i] == 2) || (mme_config_p->gummei.plmn_mnc_len[i] == 3),
"Bad MNC length %u, must be 2 or 3", mme_config_p->gummei.plmn_mnc_len[i]);
}
if( (config_setting_lookup_string( sub2setting, MME_CONFIG_STRING_TAC, &tac) )) {
mme_config_p->gummei.plmn_tac[i] = (uint16_t)atoi(tac);
AssertFatal(mme_config_p->gummei.plmn_tac[i] != 0,
"TAC must not be 0");
}
}
}
}
}
// NETWORK INTERFACE SETTING
setting = config_setting_get_member (setting_mme, MME_CONFIG_STRING_NETWORK_INTERFACES_CONFIG);
if(setting != NULL) {
if( (
config_setting_lookup_string( setting, MME_CONFIG_STRING_INTERFACE_NAME_FOR_S1_MME,
(const char **)&mme_interface_name_for_S1_MME)
&& config_setting_lookup_string( setting, MME_CONFIG_STRING_IPV4_ADDRESS_FOR_S1_MME,
(const char **)&mme_ip_address_for_S1_MME)
&& config_setting_lookup_string( setting, MME_CONFIG_STRING_INTERFACE_NAME_FOR_S11_MME,
(const char **)&mme_interface_name_for_S11)
&& config_setting_lookup_string( setting, MME_CONFIG_STRING_IPV4_ADDRESS_FOR_S11_MME,
(const char **)&mme_ip_address_for_S11)
)
) {
mme_config_p->ipv4.mme_interface_name_for_S1_MME = strdup(mme_interface_name_for_S1_MME);
cidr = strdup(mme_ip_address_for_S1_MME);
address = strtok(cidr, "/");
IPV4_STR_ADDR_TO_INT_NWBO ( address, mme_config_p->ipv4.mme_ip_address_for_S1_MME, "BAD IP ADDRESS FORMAT FOR MME S1_MME !\n" )
free(cidr);
mme_config_p->ipv4.mme_interface_name_for_S11 = strdup(mme_interface_name_for_S11);
cidr = strdup(mme_ip_address_for_S11);
address = strtok(cidr, "/");
IPV4_STR_ADDR_TO_INT_NWBO ( address, mme_config_p->ipv4.mme_ip_address_for_S11, "BAD IP ADDRESS FORMAT FOR MME S11 !\n" )
free(cidr);
if (strncasecmp("tun",mme_config_p->ipv4.mme_interface_name_for_S1_MME, strlen("tun")) == 0) {
if (snprintf(system_cmd, 256,
"ip link set %s down ;openvpn --rmtun --dev %s",
mme_config_p->ipv4.mme_interface_name_for_S1_MME,
mme_config_p->ipv4.mme_interface_name_for_S1_MME
) > 0) {
mme_system(system_cmd, 1);
} else {
fprintf(stderr, "Del %s\n", mme_config_p->ipv4.mme_interface_name_for_S1_MME);
}
if (snprintf(system_cmd, 256,
"openvpn --mktun --dev %s;sync;ifconfig %s up;sync",
mme_config_p->ipv4.mme_interface_name_for_S1_MME,
mme_config_p->ipv4.mme_interface_name_for_S1_MME) > 0) {
mme_system(system_cmd, 1);
} else {
fprintf(stderr, "Create %s\n", mme_config_p->ipv4.mme_interface_name_for_S1_MME);
}
if (snprintf(system_cmd, 256,
"ip -4 addr add %s dev %s",
mme_ip_address_for_S1_MME,
mme_config_p->ipv4.mme_interface_name_for_S1_MME) > 0) {
mme_system(system_cmd, 1);
} else {
fprintf(stderr, "Set IPv4 address on %s\n", mme_config_p->ipv4.mme_interface_name_for_S1_MME);
}
}
}
}
// NAS SETTING
setting = config_setting_get_member (setting_mme, MME_CONFIG_STRING_NAS_CONFIG);
if (setting != NULL) {
subsetting = config_setting_get_member (setting, MME_CONFIG_STRING_NAS_SUPPORTED_INTEGRITY_ALGORITHM_LIST);
if (subsetting != NULL) {
num = config_setting_length(subsetting);
if (num <= 8) {
for (i = 0; i < num; i++) {
astring = config_setting_get_string_elem(subsetting, i);
if (strcmp("EIA0", astring) == 0) mme_config_p->nas_config.prefered_integrity_algorithm[i] = NAS_CONFIG_SECURITY_ALGORITHMS_EIA0;
else if (strcmp("EIA1", astring) == 0) mme_config_p->nas_config.prefered_integrity_algorithm[i] = NAS_CONFIG_SECURITY_ALGORITHMS_EIA1;
else if (strcmp("EIA2", astring) == 0) mme_config_p->nas_config.prefered_integrity_algorithm[i] = NAS_CONFIG_SECURITY_ALGORITHMS_EIA2;
else if (strcmp("EIA3", astring) == 0) mme_config_p->nas_config.prefered_integrity_algorithm[i] = NAS_CONFIG_SECURITY_ALGORITHMS_EIA0;
else if (strcmp("EIA4", astring) == 0) mme_config_p->nas_config.prefered_integrity_algorithm[i] = NAS_CONFIG_SECURITY_ALGORITHMS_EIA0;
else if (strcmp("EIA5", astring) == 0) mme_config_p->nas_config.prefered_integrity_algorithm[i] = NAS_CONFIG_SECURITY_ALGORITHMS_EIA0;
else if (strcmp("EIA6", astring) == 0) mme_config_p->nas_config.prefered_integrity_algorithm[i] = NAS_CONFIG_SECURITY_ALGORITHMS_EIA0;
else if (strcmp("EIA7", astring) == 0) mme_config_p->nas_config.prefered_integrity_algorithm[i] = NAS_CONFIG_SECURITY_ALGORITHMS_EIA0;
}
for (i = num; i < 8; i++) {
mme_config_p->nas_config.prefered_integrity_algorithm[i] = NAS_CONFIG_SECURITY_ALGORITHMS_EIA0;
}
}
}
subsetting = config_setting_get_member (setting, MME_CONFIG_STRING_NAS_SUPPORTED_CIPHERING_ALGORITHM_LIST);
if (subsetting != NULL) {
num = config_setting_length(subsetting);
if (num <= 8) {
for (i = 0; i < num; i++) {
astring = config_setting_get_string_elem(subsetting, i);
if (strcmp("EEA0", astring) == 0) mme_config_p->nas_config.prefered_ciphering_algorithm[i] = NAS_CONFIG_SECURITY_ALGORITHMS_EEA0;
else if (strcmp("EEA1", astring) == 0) mme_config_p->nas_config.prefered_ciphering_algorithm[i] = NAS_CONFIG_SECURITY_ALGORITHMS_EEA1;
else if (strcmp("EEA2", astring) == 0) mme_config_p->nas_config.prefered_ciphering_algorithm[i] = NAS_CONFIG_SECURITY_ALGORITHMS_EEA2;
else if (strcmp("EEA3", astring) == 0) mme_config_p->nas_config.prefered_ciphering_algorithm[i] = NAS_CONFIG_SECURITY_ALGORITHMS_EEA0;
else if (strcmp("EEA4", astring) == 0) mme_config_p->nas_config.prefered_ciphering_algorithm[i] = NAS_CONFIG_SECURITY_ALGORITHMS_EEA0;
else if (strcmp("EEA5", astring) == 0) mme_config_p->nas_config.prefered_ciphering_algorithm[i] = NAS_CONFIG_SECURITY_ALGORITHMS_EEA0;
else if (strcmp("EEA6", astring) == 0) mme_config_p->nas_config.prefered_ciphering_algorithm[i] = NAS_CONFIG_SECURITY_ALGORITHMS_EEA0;
else if (strcmp("EEA7", astring) == 0) mme_config_p->nas_config.prefered_ciphering_algorithm[i] = NAS_CONFIG_SECURITY_ALGORITHMS_EEA0;
}
for (i = num; i < 8; i++) {
mme_config_p->nas_config.prefered_ciphering_algorithm[i] = NAS_CONFIG_SECURITY_ALGORITHMS_EEA0;
}
}
}
}
}
setting = config_lookup(&cfg, SGW_CONFIG_STRING_SGW_CONFIG);
if(setting != NULL) {
subsetting = config_setting_get_member (setting, SGW_CONFIG_STRING_NETWORK_INTERFACES_CONFIG);
if(subsetting != NULL) {
if( (
config_setting_lookup_string( subsetting, SGW_CONFIG_STRING_SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP,
(const char **)&sgw_ip_address_for_S1u_S12_S4_up)
&& config_setting_lookup_string( subsetting, SGW_CONFIG_STRING_SGW_IPV4_ADDRESS_FOR_S11,
(const char **)&sgw_ip_address_for_S11)
&& config_setting_lookup_int( subsetting, SGW_CONFIG_STRING_SGW_PORT_FOR_S1U_S12_S4_UP, &alongint)
)
) {
cidr = strdup(sgw_ip_address_for_S1u_S12_S4_up);
address = strtok(cidr, "/");
IPV4_STR_ADDR_TO_INT_NWBO ( address, mme_config_p->ipv4.sgw_ip_address_for_S1u_S12_S4_up, "BAD IP ADDRESS FORMAT FOR SGW S1u_S12_S4 !\n" )
free(cidr);
cidr = strdup(sgw_ip_address_for_S11);
address = strtok(cidr, "/");
IPV4_STR_ADDR_TO_INT_NWBO ( address, mme_config_p->ipv4.sgw_ip_address_for_S11, "BAD IP ADDRESS FORMAT FOR SGW S11 !\n" )
free(cidr);
mme_config_p->gtpv1u_config.port_number = (uint16_t) alongint;
}
}
}
return 0;
}
#define DISPLAY_ARRAY(size, format, args...) \
do { \
int i; \
for (i = 0; i < size; i++) { \
fprintf(stdout, format, args); \
if ((i != (size - 1)) && ((i + 1) % 10 == 0)) \
{ \
fprintf(stdout, "\n "); \
} \
} \
if (i > 0) \
fprintf(stdout, "\n"); \
} while(0)
static void config_display(mme_config_t *mme_config_p)
{
int j;
fprintf(stdout, "==== EURECOM %s v%s ====\n", PACKAGE_NAME, PACKAGE_VERSION);
fprintf(stdout, "Configuration:\n");
fprintf(stdout, "- File ...............: %s\n", mme_config_p->config_file);
fprintf(stdout, "- Verbosity level ....: %d\n", mme_config_p->verbosity_level);
fprintf(stdout, "- Realm ..............: %s\n", mme_config_p->realm);
fprintf(stdout, "- Max eNBs ...........: %u\n", mme_config_p->max_eNBs);
fprintf(stdout, "- Max UEs ............: %u\n", mme_config_p->max_ues);
fprintf(stdout, "- Emergency support ..: %s\n", mme_config_p->emergency_attach_supported == 0 ? "FALSE" : "TRUE");
fprintf(stdout, "- Unauth IMSI support : %s\n", mme_config_p->unauthenticated_imsi_supported == 0 ? "FALSE" : "TRUE");
fprintf(stdout, "- Relative capa ......: %u\n\n", mme_config_p->relative_capacity);
fprintf(stdout, "- Statistics timer ...: %u (seconds)\n\n", mme_config_p->mme_statistic_timer);
fprintf(stdout, "- S1-U:\n");
fprintf(stdout, " port number ......: %d\n", mme_config_p->gtpv1u_config.port_number);
fprintf(stdout, "- S1-MME:\n");
fprintf(stdout, " port number ......: %d\n", mme_config_p->s1ap_config.port_number);
fprintf(stdout, "- IP:\n");
//fprintf(stdout, " s1-u iface .......: %s\n", mme_config_p->ipv4.sgw_interface_name_for_S1u_S12_S4_up);
fprintf(stdout, " s1-u ip ..........: %s\n",
inet_ntoa(*((struct in_addr *)&mme_config_p->ipv4.sgw_ip_address_for_S1u_S12_S4_up)));
//fprintf(stdout, " sgi iface ........: %s\n", mme_config_p->ipv4.pgw_interface_name_for_SGI);
//fprintf(stdout, " sgi ip ...........: %s/%d\n",
// inet_ntoa(*((struct in_addr *)&mme_config_p->ipv4.pgw_ip_addr_for_SGI)),
// mme_config_p->ipv4.pgw_ip_netmask_for_SGI);
fprintf(stdout, " s1-MME iface .....: %s\n", mme_config_p->ipv4.mme_interface_name_for_S1_MME);
fprintf(stdout, " s1-MME ip ........: %s\n",
inet_ntoa(*((struct in_addr *)&mme_config_p->ipv4.mme_ip_address_for_S1_MME)));
//fprintf(stdout, " s11 S-GW iface ...: %s\n", mme_config_p->ipv4.sgw_interface_name_for_S11);
//fprintf(stdout, " s11 S-GW ip ......: %s/%d\n",
// inet_ntoa(*((struct in_addr *)&mme_config_p->ipv4.sgw_ip_address_for_S11)),
// mme_config_p->ipv4.sgw_ip_netmask_for_S11);
fprintf(stdout, " s11 MME iface ....: %s\n", mme_config_p->ipv4.mme_interface_name_for_S11);
fprintf(stdout, " s11 S-GW ip ......: %s\n",
inet_ntoa(*((struct in_addr *)&mme_config_p->ipv4.mme_ip_address_for_S11)));
fprintf(stdout, "- ITTI:\n");
fprintf(stdout, " queue size .......: %u (bytes)\n", mme_config_p->itti_config.queue_size);
fprintf(stdout, " log file .........: %s\n", mme_config_p->itti_config.log_file);
fprintf(stdout, "- SCTP:\n");
fprintf(stdout, " in streams .......: %u\n", mme_config_p->sctp_config.in_streams);
fprintf(stdout, " out streams ......: %u\n", mme_config_p->sctp_config.out_streams);
fprintf(stdout, "- GUMMEI:\n");
fprintf(stdout, " mme group ids ....:\n ");
DISPLAY_ARRAY(mme_config_p->gummei.nb_mme_gid, "| %u ", mme_config_p->gummei.mme_gid[i]);
fprintf(stdout, " mme codes ........:\n ");
DISPLAY_ARRAY(mme_config_p->gummei.nb_mmec, "| %u ", mme_config_p->gummei.mmec[i]);
fprintf(stdout, " plmns ............: (mcc.mnc:tac)\n");
for (j= 0; j < mme_config_p->gummei.nb_plmns; j++) {
if (mme_config_p->gummei.plmn_mnc_len[j] ==2 ) {
fprintf(stdout, " %3u.%3u:%u\n",
mme_config_p->gummei.plmn_mcc[j],
mme_config_p->gummei.plmn_mnc[j],
mme_config_p->gummei.plmn_tac[j]);
} else {
fprintf(stdout, " %3u.%03u:%u\n",
mme_config_p->gummei.plmn_mcc[j],
mme_config_p->gummei.plmn_mnc[j],
mme_config_p->gummei.plmn_tac[j]);
}
}
fprintf(stdout, "- S6A:\n");
fprintf(stdout, " conf file ........: %s\n", mme_config_p->s6a_config.conf_file);
}
static void usage(void)
{
fprintf(stdout, "==== EURECOM %s v%s ====\n", PACKAGE_NAME, PACKAGE_VERSION);
fprintf(stdout, "Please report any bug to: %s\n\n", PACKAGE_BUGREPORT);
fprintf(stdout, "Usage: oaisim_mme [options]\n\n");
fprintf(stdout, "Available options:\n");
fprintf(stdout, "-h Print this help and return\n");
fprintf(stdout, "-i\n");
fprintf(stdout, " Set the network card to use for IPv4 forwarding\n");
fprintf(stdout, "-c\n");
fprintf(stdout, " Set the configuration file for mme\n");
fprintf(stdout, " See template in UTILS/CONF\n");
fprintf(stdout, "-K\n");
fprintf(stdout, " Output intertask messages to provided file\n");
fprintf(stdout, "-V Print %s version and return\n", PACKAGE_NAME);
fprintf(stdout, "-v[1-2] Debug level:\n");
fprintf(stdout, " 1 -> ASN1 XER printf on and ASN1 debug off\n");
fprintf(stdout, " 2 -> ASN1 XER printf on and ASN1 debug on\n");
}
extern void
nwGtpv1uDisplayBanner(void);
int config_parse_opt_line(int argc, char *argv[], mme_config_t *mme_config_p)
{
int c;
mme_config_init(mme_config_p);
/* Parsing command line */
while ((c = getopt (argc, argv, "c:hi:K:v:V")) != -1) {
switch (c) {
case 'c': {
/* Store the given configuration file. If no file is given,
* then the default values will be used.
*/
int config_file_len = 0;
config_file_len = strlen(optarg);
mme_config_p->config_file = malloc(sizeof(char) * (config_file_len + 1));
memcpy(mme_config_p->config_file, optarg, config_file_len);
mme_config_p->config_file[config_file_len] = '\0';
} break;
/*case 'i': {
int interface_len = 0;
// Copying provided interface name to use for ipv4 forwarding
interface_len = strlen(optarg);
mme_config_p->ipv4.sgw_interface_name_for_S1u_S12_S4_up = calloc(interface_len + 1, sizeof(char));
memcpy(mme_config_p->ipv4.sgw_interface_name_for_S1u_S12_S4_up, optarg, interface_len);
mme_config_p->ipv4.sgw_interface_name_for_S1u_S12_S4_up[interface_len] = '\0';
} break;*/
case 'v': {
mme_config_p->verbosity_level = atoi(optarg);
} break;
case 'V': {
fprintf(stdout, "==== EURECOM %s v%s ====\n"
"Please report any bug to: %s\n", PACKAGE_NAME, PACKAGE_VERSION,
PACKAGE_BUGREPORT);
exit(0);
nwGtpv1uDisplayBanner();
} break;
case 'K':
mme_config_p->itti_config.log_file = strdup(optarg);
break;
case 'h': /* Fall through */
default:
usage();
exit(0);
}
}
/* Parse the configuration file using libconfig */
if (config_parse_file(mme_config_p) != 0) {
return -1;
}
/* Display the configuration */
config_display(mme_config_p);
return 0;
}