//----------------------------------------------------------------------------- sgw_pdn_connection_t * sgw_lite_cm_create_pdn_connection ( void) //----------------------------------------------------------------------------- { sgw_pdn_connection_t *pdn_connection; pdn_connection = malloc (sizeof (sgw_pdn_connection_t)); if (pdn_connection == NULL) { /* * Malloc failed, may be ENOMEM error */ SPGW_APP_ERROR ("Failed to create new PDN connection object\n"); return NULL; } memset (pdn_connection, 0, sizeof (sgw_pdn_connection_t)); pdn_connection->sgw_eps_bearers = hashtable_create (12, NULL, NULL, "sgw_eps_bearers"); if (pdn_connection->sgw_eps_bearers == NULL) { SPGW_APP_ERROR ("Failed to create eps bearers collection object\n"); free (pdn_connection); pdn_connection = NULL; return NULL; } return pdn_connection; }
//----------------------------------------------------------------------------- mme_sgw_tunnel_t * sgw_lite_cm_create_s11_tunnel ( Teid_t remote_teid, Teid_t local_teid) //----------------------------------------------------------------------------- { mme_sgw_tunnel_t *new_tunnel; new_tunnel = malloc (sizeof (mme_sgw_tunnel_t)); if (new_tunnel == NULL) { /* * Malloc failed, may be ENOMEM error */ SPGW_APP_ERROR ("Failed to create tunnel for remote_teid %u\n", remote_teid); return NULL; } new_tunnel->remote_teid = remote_teid; new_tunnel->local_teid = local_teid; /* * Trying to insert the new tunnel into the tree. * * * * If collision_p is not NULL (0), it means tunnel is already present. */ hashtable_insert (sgw_app.s11teid2mme_hashtable, local_teid, new_tunnel); return new_tunnel; }
//----------------------------------------------------------------------------- s_plus_p_gw_eps_bearer_context_information_t * sgw_lite_cm_create_bearer_context_information_in_collection ( Teid_t teid) //----------------------------------------------------------------------------- { s_plus_p_gw_eps_bearer_context_information_t *new_bearer_context_information; new_bearer_context_information = malloc (sizeof (s_plus_p_gw_eps_bearer_context_information_t)); if (new_bearer_context_information == NULL) { /* * Malloc failed, may be ENOMEM error */ SPGW_APP_ERROR ("Failed to create new bearer context information object for S11 remote_teid %u\n", teid); return NULL; } memset (new_bearer_context_information, 0, sizeof (s_plus_p_gw_eps_bearer_context_information_t)); SPGW_APP_DEBUG ("sgw_lite_cm_create_bearer_context_information_in_collection %d\n", teid); /* * new_bearer_context_information->sgw_eps_bearer_context_information.pdn_connections = obj_hashtable_create(32, NULL, NULL, sgw_lite_cm_free_pdn_connection); * * if ( new_bearer_context_information->sgw_eps_bearer_context_information.pdn_connections == NULL) { * SPGW_APP_ERROR("Failed to create PDN connections collection object entry for EPS bearer teid %u \n", teid); * sgw_lite_cm_free_s_plus_p_gw_eps_bearer_context_information(new_bearer_context_information); * return NULL; * } */ new_bearer_context_information->pgw_eps_bearer_context_information.apns = obj_hashtable_create (32, NULL, NULL, pgw_lite_cm_free_apn, "pgw_eps_bearer_ctxt_info_apns"); if (new_bearer_context_information->pgw_eps_bearer_context_information.apns == NULL) { SPGW_APP_ERROR ("Failed to create APN collection object entry for EPS bearer S11 teid %u \n", teid); sgw_lite_cm_free_s_plus_p_gw_eps_bearer_context_information (new_bearer_context_information); return NULL; } /* * Trying to insert the new tunnel into the tree. * * * * If collision_p is not NULL (0), it means tunnel is already present. */ hashtable_insert (sgw_app.s11_bearer_context_information_hashtable, teid, new_bearer_context_information); SPGW_APP_DEBUG ("Added new s_plus_p_gw_eps_bearer_context_information_t in s11_bearer_context_information_hashtable key teid %u\n", teid); return new_bearer_context_information; }
//----------------------------------------------------------------------------- sgw_eps_bearer_entry_t * sgw_lite_cm_create_eps_bearer_entry_in_collection ( hash_table_t * eps_bearersP, ebi_t eps_bearer_idP) //----------------------------------------------------------------------------- { sgw_eps_bearer_entry_t *new_eps_bearer_entry; hashtable_rc_t hash_rc = HASH_TABLE_OK; if (eps_bearersP == NULL) { SPGW_APP_ERROR ("Failed to create EPS bearer entry for EPS bearer id %u. reason eps bearer hashtable is NULL \n", eps_bearer_idP); return NULL; } new_eps_bearer_entry = malloc (sizeof (sgw_eps_bearer_entry_t)); if (new_eps_bearer_entry == NULL) { /* * Malloc failed, may be ENOMEM error */ SPGW_APP_ERROR ("Failed to create EPS bearer entry for EPS bearer id %u \n", eps_bearer_idP); return NULL; } memset (new_eps_bearer_entry, 0, sizeof (sgw_eps_bearer_entry_t)); new_eps_bearer_entry->eps_bearer_id = eps_bearer_idP; hash_rc = hashtable_insert (eps_bearersP, eps_bearer_idP, new_eps_bearer_entry); SPGW_APP_DEBUG ("Inserted new EPS bearer entry for EPS bearer id %u status %s\n", eps_bearer_idP, hashtable_rc_code2string (hash_rc)); hash_rc = hashtable_apply_funct_on_elements (eps_bearersP, sgw_lite_display_pdn_connection_sgw_eps_bearers, NULL); if (hash_rc != HASH_TABLE_OK) { SPGW_APP_DEBUG ("Invalid sgw_eps_bearers hashtable for display\n"); } /* * CHECK DUPLICATES IN HASH TABLES ? if (temp == 1) { * SPGW_APP_WARN("This EPS bearer entry already exists: %u\n", eps_bearer_idP); * free(new_eps_bearer_entry); * new_eps_bearer_entry = collision_p; * } */ return new_eps_bearer_entry; }
//----------------------------------------------------------------------------- sgw_eps_bearer_entry_t * sgw_lite_cm_create_eps_bearer_entry ( void) //----------------------------------------------------------------------------- { sgw_eps_bearer_entry_t *eps_bearer_entry; eps_bearer_entry = malloc (sizeof (sgw_eps_bearer_entry_t)); if (eps_bearer_entry == NULL) { /* * Malloc failed, may be ENOMEM error */ SPGW_APP_ERROR ("Failed to create new EPS bearer object\n"); return NULL; } return eps_bearer_entry; }
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 {