/******************************************************************************* Eurecom OpenAirInterface Copyright(c) 1999 - 2013 Eurecom This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope 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., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information Openair Admin: openair_admin@eurecom.fr Openair Tech : openair_tech@eurecom.fr Forums : http://forums.eurecom.fr/openairinterface Address : EURECOM, Campus SophiaTech, 450 Route des Chappes 06410 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; 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; } 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; 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_SCTP_OUTSTREAMS, &alongint) )) { mme_config_p->sctp_config.out_streams = (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); } } } 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) ) ) { 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); } } } 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/%d\n", // inet_ntoa(*((struct in_addr *)&mme_config_p->ipv4.sgw_ip_address_for_S1u_S12_S4_up)), // mme_config_p->ipv4.sgw_ip_netmask_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 yhe configuration */ config_display(mme_config_p); return 0; }