Files
openairinterface5g/openair-cn/MME_APP/mme_app_config.c
T
Lionel Gauthier 059a0a3fdc astyle --recursive --indent=spaces=2 --style=kr --indent-col1-comments --break-blocks --convert-tabs --max-code-length=200
This is done for better merging branch/LG_PRE_RELEASE_0.3 into trunk (same process is applied on this branch)

git-svn-id: http://svn.eurecom.fr/openair4G/trunk@7073 818b1a75-f10b-46b9-bf7c-635c3b92a50f
2015-04-09 09:29:12 +00:00

308 lines
14 KiB
C
Executable File

/*******************************************************************************
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 <http://www.gnu.org/licenses/>.
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.
*******************************************************************************/
/*! \file mme_app_config.c
* \brief
* \author Lionel GAUTHIER
* \version 1.0
* \company Eurecom
* \email: lionel.gauthier@eurecom.fr
*/
#define MME_APP
#define MME_APP_CONFIG_C
#include <string.h>
#include <libconfig.h>
#include "mme_app_config.h"
int mme_app_config_init(char* lib_config_file_name_pP, mme_app_config_t* config_pP)
{
config_t cfg;
config_setting_t *setting_sgw = NULL;
char *sgw_interface_name_for_S1u_S12_S4_up = NULL;
char *sgw_ipv4_address_for_S1u_S12_S4_up = NULL;
char *sgw_interface_name_for_S5_S8_up = NULL;
char *sgw_ipv4_address_for_S5_S8_up = NULL;
char *sgw_interface_name_for_S11 = NULL;
char *sgw_ipv4_address_for_S11 = NULL;
config_setting_t *setting_pgw = NULL;
config_setting_t *subsetting = NULL;
config_setting_t *sub2setting = NULL;
char *pgw_interface_name_for_S5_S8 = NULL;
char *pgw_ipv4_address_for_S5_S8 = NULL;
char *pgw_interface_name_for_SGI = NULL;
char *pgw_ipv4_address_for_SGI = NULL;
char *delimiters=NULL;
char *saveptr1= NULL;
char *astring = NULL;
char *atoken = NULL;
char *atoken2 = NULL;
char *address = NULL;
char *cidr = NULL;
char *mask = NULL;
int num = 0;
int i = 0;
int jh, jn;
unsigned char buf_in6_addr[sizeof(struct in6_addr)];
struct in6_addr addr6_start;
struct in6_addr addr6_mask;
int prefix_mask;
uint64_t counter64;
unsigned char buf_in_addr[sizeof(struct in_addr)];
struct in_addr addr_start;
struct in_addr addr_end;
memset((char*)config_pP, 0 , sizeof(mme_app_config_t));
config_init(&cfg);
if(lib_config_file_name_pP != NULL) {
/* Read the file. If there is an error, report it and exit. */
if(! config_read_file(&cfg, lib_config_file_name_pP)) {
MME_APP_ERROR("%s:%d - %s\n", lib_config_file_name_pP, config_error_line(&cfg), config_error_text(&cfg));
config_destroy(&cfg);
AssertFatal (1 == 0, "Failed to parse eNB configuration file %s!\n", lib_config_file_name_pP);
}
} else {
SPGW_APP_ERROR("No SP-GW configuration file provided!\n");
config_destroy(&cfg);
AssertFatal (0, "No SP-GW configuration file provided!\n");
}
setting_sgw = config_lookup(&cfg, SGW_CONFIG_STRING_SGW_CONFIG);
if(setting_sgw != NULL) {
subsetting = config_setting_get_member (setting_sgw, SGW_CONFIG_STRING_NETWORK_INTERFACES_CONFIG);
if(subsetting != NULL) {
if( (
config_setting_lookup_string( subsetting, SGW_CONFIG_STRING_SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP, (const char **)&sgw_interface_name_for_S1u_S12_S4_up)
&& config_setting_lookup_string( subsetting, SGW_CONFIG_STRING_SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP, (const char **)&sgw_ipv4_address_for_S1u_S12_S4_up)
&& config_setting_lookup_string( subsetting, SGW_CONFIG_STRING_SGW_INTERFACE_NAME_FOR_S5_S8_UP, (const char **)&sgw_interface_name_for_S5_S8_up)
&& config_setting_lookup_string( subsetting, SGW_CONFIG_STRING_SGW_IPV4_ADDRESS_FOR_S5_S8_UP, (const char **)&sgw_ipv4_address_for_S5_S8_up)
&& config_setting_lookup_string( subsetting, SGW_CONFIG_STRING_SGW_INTERFACE_NAME_FOR_S11, (const char **)&sgw_interface_name_for_S11)
&& config_setting_lookup_string( subsetting, SGW_CONFIG_STRING_SGW_IPV4_ADDRESS_FOR_S11, (const char **)&sgw_ipv4_address_for_S11)
)
) {
config_pP->sgw_config.ipv4.sgw_interface_name_for_S1u_S12_S4_up = strdup(sgw_interface_name_for_S1u_S12_S4_up);
cidr = strdup(sgw_ipv4_address_for_S1u_S12_S4_up);
address = strtok(cidr, "/");
mask = strtok(NULL, "/");
IPV4_STR_ADDR_TO_INT_NWBO ( address, config_pP->sgw_config.ipv4.sgw_ipv4_address_for_S1u_S12_S4_up, "BAD IP ADDRESS FORMAT FOR S1u_S12_S4 !\n" )
config_pP->sgw_config.ipv4.sgw_ip_netmask_for_S1u_S12_S4_up = atoi(mask);
free(cidr);
config_pP->sgw_config.ipv4.sgw_interface_name_for_S5_S8_up = strdup(sgw_interface_name_for_S5_S8_up);
cidr = strdup(sgw_ipv4_address_for_S5_S8_up);
address = strtok(cidr, "/");
mask = strtok(NULL, "/");
IPV4_STR_ADDR_TO_INT_NWBO ( address, config_pP->sgw_config.ipv4.sgw_ipv4_address_for_S5_S8_up, "BAD IP ADDRESS FORMAT FOR S5_S8 !\n" )
config_pP->sgw_config.ipv4.sgw_ip_netmask_for_S5_S8_up = atoi(mask);
free(cidr);
config_pP->sgw_config.ipv4.sgw_interface_name_for_S11 = strdup(sgw_interface_name_for_S11);
cidr = strdup(sgw_ipv4_address_for_S11);
address = strtok(cidr, "/");
mask = strtok(NULL, "/");
IPV4_STR_ADDR_TO_INT_NWBO ( address, config_pP->sgw_config.ipv4.sgw_ipv4_address_for_S11, "BAD IP ADDRESS FORMAT FOR S11 !\n" )
config_pP->sgw_config.ipv4.sgw_ip_netmask_for_S11 = atoi(mask);
free(cidr);
}
}
}
setting_pgw = config_lookup(&cfg, PGW_CONFIG_STRING_PGW_CONFIG);
if(setting_pgw != NULL) {
subsetting = config_setting_get_member (setting_pgw, SGW_CONFIG_STRING_NETWORK_INTERFACES_CONFIG);
if(subsetting != NULL) {
if( (
config_setting_lookup_string(subsetting,
PGW_CONFIG_STRING_PGW_INTERFACE_NAME_FOR_S5_S8,
(const char **)&pgw_interface_name_for_S5_S8)
&& config_setting_lookup_string(subsetting,
PGW_CONFIG_STRING_PGW_IPV4_ADDRESS_FOR_S5_S8,
(const char **)&pgw_ipv4_address_for_S5_S8)
&& config_setting_lookup_string(subsetting,
PGW_CONFIG_STRING_PGW_INTERFACE_NAME_FOR_SGI,
(const char **)&pgw_interface_name_for_SGI)
&& config_setting_lookup_string(subsetting,
PGW_CONFIG_STRING_PGW_IPV4_ADDR_FOR_SGI,
(const char **)&pgw_ipv4_address_for_SGI)
)
) {
config_pP->pgw_config.ipv4.pgw_interface_name_for_S5_S8 = strdup(pgw_interface_name_for_S5_S8);
cidr = strdup(pgw_ipv4_address_for_S5_S8);
address = strtok(cidr, "/");
mask = strtok(NULL, "/");
IPV4_STR_ADDR_TO_INT_NWBO ( address, config_pP->pgw_config.ipv4.pgw_ipv4_address_for_S5_S8, "BAD IP ADDRESS FORMAT FOR S5_S8 !\n" )
config_pP->pgw_config.ipv4.pgw_ip_netmask_for_S5_S8 = atoi(mask);
free(cidr);
config_pP->pgw_config.ipv4.pgw_interface_name_for_SGI = strdup(pgw_interface_name_for_SGI);
cidr = strdup(pgw_ipv4_address_for_SGI);
address = strtok(cidr, "/");
mask = strtok(NULL, "/");
IPV4_STR_ADDR_TO_INT_NWBO ( address, config_pP->pgw_config.ipv4.pgw_ipv4_address_for_SGI, "BAD IP ADDRESS FORMAT FOR SGI !\n" )
config_pP->pgw_config.ipv4.pgw_ip_netmask_for_SGI = atoi(mask);
free(cidr);
}
}
subsetting = config_setting_get_member (setting_pgw, PGW_CONFIG_STRING_IP_ADDRESS_POOL);
if(subsetting != NULL) {
sub2setting = config_setting_get_member (subsetting, PGW_CONFIG_STRING_IPV4_ADDRESS_LIST);
if(sub2setting != NULL) {
num = config_setting_length(sub2setting);
for (i = 0; i < num; i++) {
astring = config_setting_get_string_elem(sub2setting,i);
if (astring != NULL) {
trim(astring, strlen(astring)+1);
if (inet_pton(AF_INET, astring, buf_in_addr) < 1) {
// failure, test if there is a range specified in the string
atoken = strtok(astring, PGW_CONFIG_STRING_IP_ADDRESS_RANGE_DELIMITERS);
if (inet_pton(AF_INET, astring, buf_in_addr) == 1) {
memcpy (&addr_start, buf_in_addr, sizeof(struct in_addr));
// valid address
atoken2 = strtok(NULL, PGW_CONFIG_STRING_IP_ADDRESS_RANGE_DELIMITERS);
if (inet_pton(AF_INET, atoken2, buf_in_addr) == 1) {
memcpy (&addr_end, buf_in_addr, sizeof(struct in_addr));
// valid address
for (jh = ntohl(addr_start.s_addr); jh <= ntohl(addr_end.s_addr); jh++) {
DevAssert(PGW_MAX_ALLOCATED_PDN_ADDRESSES > config_pP->pgw_config.pool_pdn_addresses.num_ipv4_addresses);
jn = htonl(jh);
if (IN_CLASSA(addr_start.s_addr)) {
if ((jh & 0xFF) && (jh & 0xFF) != 0xFF) {
config_pP->pgw_config.pool_pdn_addresses.ipv4_addresses[config_pP->pgw_config.pool_pdn_addresses.num_ipv4_addresses++].s_addr = jn;
}
} else if (IN_CLASSB(addr_start.s_addr)) {
if ((jh & 0xFF) && (jh & 0xFF) != 0xFF) {
config_pP->pgw_config.pool_pdn_addresses.ipv4_addresses[config_pP->pgw_config.pool_pdn_addresses.num_ipv4_addresses++].s_addr = jn;
}
} else if (IN_CLASSC(addr_start.s_addr)) {
if ((jh & 0xFF) && (jh & 0xFF) != 0xFF) {
config_pP->pgw_config.pool_pdn_addresses.ipv4_addresses[config_pP->pgw_config.pool_pdn_addresses.num_ipv4_addresses++].s_addr = jn;
}
} else {
printf("ERROR ON ADDRESS CLASS %d.%d.%d.%d\n", NIPADDR(jn));
}
}
}
}
} else {
DevAssert(PGW_MAX_ALLOCATED_PDN_ADDRESSES > config_pP->pgw_config.pool_pdn_addresses.num_ipv4_addresses);
memcpy (&addr_start, buf_in_addr, sizeof(struct in_addr));
config_pP->pgw_config.pool_pdn_addresses.ipv4_addresses[config_pP->pgw_config.pool_pdn_addresses.num_ipv4_addresses++].s_addr = addr_start.s_addr;
}
}
}
}
sub2setting = config_setting_get_member (subsetting, PGW_CONFIG_STRING_IPV6_ADDRESS_LIST);
if(sub2setting != NULL) {
num = config_setting_length(sub2setting);
for (i = 0; i < num; i++) {
astring = config_setting_get_string_elem(sub2setting,i);
if (astring != NULL) {
trim(astring, strlen(astring)+1);
if (inet_pton(AF_INET6, astring, buf_in6_addr) < 1) {
// failure, test if there is a range specified in the string
atoken = strtok(astring, PGW_CONFIG_STRING_IPV6_PREFIX_DELIMITER);
if (inet_pton(AF_INET6, astring, buf_in6_addr) == 1) {
atoken2 = strtok(NULL, PGW_CONFIG_STRING_IPV6_PREFIX_DELIMITER);
prefix_mask = atoi(atoken2);
// arbitrary values
DevAssert((prefix_mask < 128) && (prefix_mask >= 64));
memcpy (&addr6_start, buf_in6_addr, sizeof(struct in6_addr));
memcpy (&addr6_mask, buf_in6_addr, sizeof(struct in6_addr));
sgw_ipv6_mask_in6_addr(&addr6_mask, prefix_mask);
if (memcmp(&addr6_start, &addr6_mask, sizeof(struct in6_addr)) != 0) {
AssertFatal(0, "BAD IPV6 ADDR CONFIG/MASK PAIRING %s/%d\n", astring, prefix_mask);
}
counter64 = 0xFFFFFFFFFFFFFFFF >> prefix_mask; // address Prefix_mask/0..0 not valid
do {
addr6_start.s6_addr32[3] = addr6_start.s6_addr32[3] + htonl(1);
if (addr6_start.s6_addr32[3] == 0) {
addr6_start.s6_addr32[2] = addr6_start.s6_addr32[2] + htonl(1);
if (addr6_start.s6_addr32[2] == 0) {
// should not happen since mask is no less than 64
addr6_start.s6_addr32[1] = addr6_start.s6_addr32[1] + htonl(1);
if (addr6_start.s6_addr32[1] == 0) {
addr6_start.s6_addr32[0] = addr6_start.s6_addr32[0] + htonl(1);
}
}
}
memcpy (&config_pP->pgw_config.pool_pdn_addresses.ipv6_addresses[config_pP->pgw_config.pool_pdn_addresses.num_ipv6_addresses++],
&addr6_start,
sizeof(struct in6_addr));
counter64 = counter64 - 1;
} while (counter64 > 0);
}
} else {
DevAssert(PGW_MAX_ALLOCATED_PDN_ADDRESSES > config_pP->pgw_config.pool_pdn_addresses.num_ipv6_addresses);
memcpy (&config_pP->pgw_config.pool_pdn_addresses.ipv6_addresses[config_pP->pgw_config.pool_pdn_addresses.num_ipv6_addresses++],
buf_in6_addr,
sizeof(struct in6_addr));
}
}
}
}
}
}
return 0;
}