//-----------------------------------------------------------------------------
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;
}
예제 #6
0
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 {