diff --git a/Dockerfile b/Dockerfile index 418da29..fcd8e52 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,7 +13,7 @@ ARG CPUS WORKDIR /c3po COPY install_builddeps.sh . COPY modules modules -COPY patches patches +COPY patches patches RUN ./install_builddeps.sh RUN rm -rf /c3po-libs && mkdir -p /c3po-libs && \ diff --git a/hss/README.txt b/hss/README.txt index 04119d9..5e05c36 100755 --- a/hss/README.txt +++ b/hss/README.txt @@ -10,7 +10,7 @@ Perform the following procedures in order. $ cd {isntallation_root}/c3po/hss $ make - + 3. Update the following files with any configuration changes: {installation_root}/c3po/hss/conf/hss.conf diff --git a/hss/db/oai_db.cql b/hss/db/oai_db.cql index 2be0a8e..62f8874 100644 --- a/hss/db/oai_db.cql +++ b/hss/db/oai_db.cql @@ -23,6 +23,7 @@ CREATE TABLE IF NOT EXISTS vhss.users_imsi ( rfsp_index varint, sqn bigint, subscription_data text, + supported_features text, ue_reachability varint, urrp_mme varint, user_identifier text, diff --git a/hss/hssperf/src/s6as6d.cpp b/hss/hssperf/src/s6as6d.cpp index f9d7d6f..1504306 100644 --- a/hss/hssperf/src/s6as6d.cpp +++ b/hss/hssperf/src/s6as6d.cpp @@ -300,7 +300,6 @@ Dictionary::Dictionary() m_avp_ext_pdp_address( "Ext-PDP-Address", m_vnd_3gpp.getId() ), m_avp_regional_subscription_zone_code( "Regional-Subscription-Zone-Code", m_vnd_3gpp.getId() ) { - std::cout << "Registering s6as6d dictionary" << std::endl; }; Dictionary::~Dictionary() diff --git a/hss/include/dataaccess.h b/hss/include/dataaccess.h index b85d487..ccbe7eb 100755 --- a/hss/include/dataaccess.h +++ b/hss/include/dataaccess.h @@ -109,12 +109,75 @@ class DAEventIdList : public std::list } }; +class ImsiEntity +{ +public: + ImsiEntity() + { + imsi = ""; imsi_pres = false; + idmmeidentity = 0; idmmeidentity_pres = false; + imei = ""; imei_pres = false; + imei_sv = ""; imei_sv_pres = false; + key = ""; key_pres = false; + lipa_permissions = ""; lipa_permissions_pres = false; + mmeidentity_idmmeidentity = 0; mmeidentity_idmmeidentity_pres = false; + mme_cap = 0; mme_cap_pres = false; + mmehost = ""; mmehost_pres = false; + mmerealm = ""; mmerealm_pres = false; + ms_ps_status = ""; ms_ps_status_pres = false; + msisdn = 0; msisdn_pres = false; + niddvalidity = ""; niddvalidity_pres = false; + nir_dest_host = ""; nir_dest_host_pres = false; + nir_dest_realm = ""; nir_dest_realm_pres = false; + opc = ""; opc_pres = false; + pgw_id = 0; pgw_id_pres = false; + rand = ""; rand_pres = false; + rfsp_index = 0; rfsp_index_pres = false; + sqn = 0; sqn_pres = false; + subscription_data = ""; subscription_data_pres = false; + supported_features = ""; supported_features_pres = false; + ue_reachability = 0; ue_reachability_pres = false; + urrp_mme = 0; urrp_mme_pres = false; + user_identifier = ""; user_identifier_pres = false; + visited_plmnid = ""; visited_plmnid_pres = false; + access_restriction = 0; access_restriction_pres = false; + } + std::string imsi; bool imsi_pres; + int32_t access_restriction; bool access_restriction_pres; + int32_t idmmeidentity; bool idmmeidentity_pres; + std::string imei; bool imei_pres; + std::string imei_sv; bool imei_sv_pres; + std::string key; bool key_pres; + std::string lipa_permissions; bool lipa_permissions_pres; + int32_t mme_cap; bool mme_cap_pres; + std::string mmehost; bool mmehost_pres; + int32_t mmeidentity_idmmeidentity; bool mmeidentity_idmmeidentity_pres; + std::string mmerealm; bool mmerealm_pres; + std::string ms_ps_status; bool ms_ps_status_pres; + int64_t msisdn; bool msisdn_pres; + std::string niddvalidity; bool niddvalidity_pres; + std::string nir_dest_host; bool nir_dest_host_pres; + std::string nir_dest_realm; bool nir_dest_realm_pres; + std::string opc; bool opc_pres; + int32_t pgw_id; bool pgw_id_pres; + std::string rand; bool rand_pres; + int32_t rfsp_index; bool rfsp_index_pres; + int32_t sqn; bool sqn_pres; + std::string subscription_data; bool subscription_data_pres; + std::string supported_features; bool supported_features_pres; + int32_t ue_reachability; bool ue_reachability_pres; + int32_t urrp_mme; bool urrp_mme_pres; + std::string user_identifier; bool user_identifier_pres; + std::string visited_plmnid; bool visited_plmnid_pres; +}; + struct DAImsiInfo { - std::string imsi; - std::string mmehost; + std::string imsi; + std::string mmehost; std::string mmerealm; std::string ms_ps_status; std::string subscription_data; + std::string supported_features; int64_t msisdn; std::string str_msisdn; std::string visited_plmnid; @@ -193,6 +256,9 @@ class DataAccess bool getImsiInfo ( const char *imsi, DAImsiInfo &info, CassFutureCallback cb, void *data ); bool getImsiInfo ( const std::string &imsi, DAImsiInfo &info, CassFutureCallback cb, void *data ) { return getImsiInfo( imsi.c_str(), info, cb, data ); } + bool deleteUserImsi(const ImsiEntity &ie, CassFutureCallback cb, void *data); + bool insertUserImsi(const ImsiEntity &ie, CassFutureCallback cb, void *data); + bool getEventIdsFromMsisdnData( SCassFuture &future, DAEventIdList &el ); bool getEventIdsFromMsisdn( int64_t msisdn, DAEventIdList &el, CassFutureCallback cb, void *data ); diff --git a/hss/include/fdhss.h b/hss/include/fdhss.h index 22c6839..55e25b4 100755 --- a/hss/include/fdhss.h +++ b/hss/include/fdhss.h @@ -148,6 +148,9 @@ class FDHss { void sendRIR_ChangeImsiImeiSvAssn(ImsiImeiData &data); + void poppulate_IMSIs(const ImsiEntity &ie); + void remove_IMSI(const ImsiEntity &ie); + s6t::Application *gets6tApp() { return m_s6tapp; } s6as6d::Application *gets6as6dApp() { return m_s6aapp; } s6c::Application *gets6cApp() { return m_s6capp; } diff --git a/hss/include/portal_config.h b/hss/include/portal_config.h new file mode 100644 index 0000000..376bab0 --- /dev/null +++ b/hss/include/portal_config.h @@ -0,0 +1,275 @@ +// Copyright 2020-present Open Networking Foundation +// +// SPDX-License-Identifier: Apache-2.0 + +#ifndef __PORTAL_CONFIG_H__ +#define __PORTAL_CONFIG_H__ + +#include "rapidjson/document.h" +#include + +class imsi_selection +{ + public: + imsi_selection() {} + ~imsi_selection() {} + bool is_valid; + uint64_t from_imsi; + uint64_t to_imsi; +}; + +class serving_plmn +{ + public: + serving_plmn() {} + ~serving_plmn() {} + bool is_valid; + uint8_t plmn[3]; + uint16_t tac; +}; + +class apn_key +{ + public: + apn_key() {} + ~apn_key() {} + bool is_valid; + std::string requested_apn; +}; + +class sub_selection_keys +{ + public: + sub_selection_keys() {} + ~sub_selection_keys() {} + imsi_selection imsi; + serving_plmn plmn; + apn_key apn; +}; + +class access_profile +{ + public: + access_profile() {} + ~access_profile() {} + std::string access_profile_name; +}; + +class qos_profile +{ + public: + qos_profile() {} + ~qos_profile() {} + std::string qos_profile_name; + uint32_t apn_ambr_ul; + uint32_t apn_ambr_dl; + uint32_t qci; + uint32_t priority; + uint32_t pre_empt_capability; + uint32_t pre_empt_vulnerability; +}; + +class user_plane_profile +{ + public: + user_plane_profile() {} + ~user_plane_profile() {} + std::string user_plane_profile_name; + std::string user_plane_service; + uint32_t upf_addr; /* run time information */ +}; + +class apn_profile +{ + public: + apn_profile() {} + ~apn_profile() {} + std::string apn_profile_name; + std::string apn_name; + uint8_t apn_name_length; + int apn_usage_type; + std::string apn_net_cap; + bool gx_enabled; + uint32_t dns_primary; + uint32_t dns_secondary; + uint16_t mtu; +}; + +class security_profile +{ + public: + security_profile() {} + ~security_profile() {} + std::string name; + std::string key; + std::string opc; + uint64_t sqn; +}; + +class sub_selection_rule +{ + public: + sub_selection_rule() {} + ~sub_selection_rule() + { + delete keys; + } + uint32_t rule_priority; + sub_selection_keys *keys; + std::string selected_apn_profile; + std::string selected_user_plane_profile; + std::string selected_qos_profile; + std::string selected_access_profile[4]; /* 4 access profiles per subscriber */ + std::string selected_security_profile; +}; + +class portalConfig +{ + public: + portalConfig() {;} + ~portalConfig() + { + for (std::list ::iterator it=sub_sel_rules.begin(); it!=sub_sel_rules.end(); ++it) + { + sub_selection_rule *rule = *it; + delete rule; + } + + for (std::list::iterator it=apn_profile_list.begin(); it!=apn_profile_list.end(); ++it) + { + apn_profile *apn=*it; + delete apn; + } + for (std::list::iterator it=user_plane_list.begin(); it!=user_plane_list.end(); ++it) + { + user_plane_profile *up=*it; + delete up; + } + for (std::list::iterator it=qos_profile_list.begin(); it!=qos_profile_list.end(); ++it) + { + qos_profile *qos=*it; + delete qos; + } + for (std::list::iterator it=access_profile_list.begin(); it!=access_profile_list.end(); ++it) + { + access_profile *access=*it; + delete access; + } + } + + apn_profile* get_apn_profile(const std::string name) + { + for (std::list::iterator it=apn_profile_list.begin(); it!=apn_profile_list.end(); ++it) + { + apn_profile *apn=*it; + if(apn->apn_profile_name.compare(name) == 0) + return apn; + } + return nullptr; + } + + user_plane_profile* get_user_plane_profile(const std::string name) + { + for (std::list::iterator it=user_plane_list.begin(); it!=user_plane_list.end(); ++it) + { + user_plane_profile *up=*it; + if(up->user_plane_profile_name.compare(name) == 0) + return up; + } + return nullptr; + } + + qos_profile* get_qos_profile(const std::string name) + { + for (std::list::iterator it=qos_profile_list.begin(); it!=qos_profile_list.end(); ++it) + { + qos_profile *qos=*it; + if(qos->qos_profile_name.compare(name) == 0) + return qos; + } + return nullptr; + } + + security_profile* get_security_profile(const std::string name) + { + for (std::list::iterator it=security_profile_list.begin(); it!=security_profile_list.end(); ++it) + { + security_profile *sec=*it; + if(sec->name.compare(name) == 0) + return sec; + } + return nullptr; + } + + access_profile* get_access_profile(const std::string name) + { + for (std::list::iterator it=access_profile_list.begin(); it!=access_profile_list.end(); ++it) + { + access_profile *access=*it; + if(access->access_profile_name.compare(name) == 0) + return access; + } + return nullptr; + } + public: + std::list sub_sel_rules; + std::list apn_profile_list; + std::list user_plane_list; + std::list access_profile_list; + std::list qos_profile_list; + std::list security_profile_list; +}; + +class newPortalConfig +{ + public: + newPortalConfig() + { + key = ""; + opc = ""; + sqn = 0; + from_imsi = 0; + to_imsi = 0; + apn_ambr_ul = 0; + apn_ambr_dl = 0; + qci = 0; + arp = 0; + } + ~newPortalConfig() + { + for (std::list::iterator it=apn_profile_list.begin(); it!=apn_profile_list.end(); ++it) + { + apn_profile *apn=*it; + delete apn; + } + } + + apn_profile* get_apn_profile(const std::string name) + { + for (std::list::iterator it=apn_profile_list.begin(); it!=apn_profile_list.end(); ++it) + { + apn_profile *apn=*it; + if(apn->apn_profile_name.compare(name) == 0) + return apn; + } + return nullptr; + } + + public: + std::string key; + std::string opc; + uint64_t sqn; + uint64_t from_imsi; + uint64_t to_imsi; + uint32_t apn_ambr_ul; + uint32_t apn_ambr_dl; + uint32_t qci; + uint32_t arp; + std::list apn_profile_list; +}; + +extern "C" { + portalConfig *parse_json_doc(RAPIDJSON_NAMESPACE::Document &doc); + newPortalConfig *parse_hss_json_doc(RAPIDJSON_NAMESPACE::Document &doc); +} +#endif diff --git a/hss/src/dataaccess.cpp b/hss/src/dataaccess.cpp index e8577c1..d30d77e 100755 --- a/hss/src/dataaccess.cpp +++ b/hss/src/dataaccess.cpp @@ -732,6 +732,7 @@ bool DataAccess::getImsiInfoData( SCassFuture &future, DAImsiInfo &info ) GET_EVENT_DATA( row, mmerealm, info.mmerealm ); GET_EVENT_DATA( row, ms_ps_status, info.ms_ps_status ); GET_EVENT_DATA( row, subscription_data, info.subscription_data ); + GET_EVENT_DATA( row, supported_features, info.supported_features); GET_EVENT_DATA( row, msisdn, info.msisdn ); info.str_msisdn = std::to_string( info.msisdn ); GET_EVENT_DATA( row, visited_plmnid, info.visited_plmnid ); @@ -747,7 +748,7 @@ bool DataAccess::getImsiInfo ( const char *imsi, DAImsiInfo &info, CassFutureCal { std::stringstream ss; - ss << "SELECT imsi, mmehost, mmerealm, ms_ps_status, subscription_data, msisdn, visited_plmnid, access_restriction, mmeidentity_idmmeidentity FROM users_imsi where imsi = '" + ss << "SELECT imsi, mmehost, mmerealm, ms_ps_status, subscription_data, supported_features, msisdn, visited_plmnid, access_restriction, mmeidentity_idmmeidentity FROM users_imsi where imsi = '" << imsi << "' ;" ; SCassStatement stmt( ss.str().c_str() ); @@ -760,6 +761,96 @@ bool DataAccess::getImsiInfo ( const char *imsi, DAImsiInfo &info, CassFutureCal return getImsiInfoData( future, info ); } +#define ADD_VALUE_STRING(_ss, _ie, _name, _comma) \ +{ \ + if (_ie._name ## _pres) \ + _ss << "'" << _ie._name << "'" _comma; \ + else \ + _ss << "null" _comma; \ +} + +#define ADD_VALUE_INT(_ss, _ie, _name, _comma) \ +{ \ + if (_ie._name ## _pres) \ + _ss << _ie._name << _comma; \ + else \ + _ss << "null" _comma; \ +} + +bool DataAccess::insertUserImsi( const ImsiEntity &ie, CassFutureCallback cb, void *data) +{ + std::stringstream ss; + + ss << "INSERT INTO vhss.users_imsi (" + << "imsi, msisdn, access_restriction, key," + << "opc, mmehost, mmeidentity_idmmeidentity, mmerealm, rand, sqn, subscription_data, supported_features" + << ") VALUES ("; + ADD_VALUE_STRING(ss, ie, imsi, ","); + ADD_VALUE_INT(ss, ie, msisdn, ","); + ADD_VALUE_INT(ss, ie, access_restriction, ","); + ADD_VALUE_STRING(ss, ie, key, ","); + ADD_VALUE_STRING(ss, ie, opc, ","); + ADD_VALUE_STRING(ss, ie, mmehost, ","); + ADD_VALUE_INT(ss, ie, mmeidentity_idmmeidentity, ","); + ADD_VALUE_STRING(ss, ie, mmerealm, ","); + ADD_VALUE_STRING(ss, ie, rand, ","); + ADD_VALUE_INT(ss, ie, sqn, ","); + ADD_VALUE_STRING(ss, ie, subscription_data, ","); + ADD_VALUE_STRING(ss, ie, supported_features, ""); + ss << ")"; + + std::cout << ss.str() << std::endl; + + SCassStatement stmt( ss.str().c_str() ); + + SCassFuture future = m_db.execute( stmt ); + + if ( future.errorCode() != CASS_OK ) + { + std::cout << "DataAccess::" << __func__ << " - Error " << future.errorCode() + << " executing [" << ss.str() << "]" << std::endl; + return false; + } + + if (cb) + return future.setCallback( cb, data ); + +#if 0 + if ( !insertUserMsisdn( ie.imsi, ie.msisdn ) ) + { + deleteUserImsi( ie.imsi ); + return false; + } +#endif + + return true; +} + +bool DataAccess::deleteUserImsi( const ImsiEntity &ie, CassFutureCallback cb, void *data) +{ + std::stringstream ss; + + ss << "DELETE FROM vhss.users_imsi WHERE imsi='"<< ie.imsi<<"'"; + + std::cout << ss.str() << std::endl; + + SCassStatement stmt( ss.str().c_str() ); + + SCassFuture future = m_db.execute( stmt ); + + if ( future.errorCode() != CASS_OK ) + { + std::cout << "DataAccess::" << __func__ << " - Error " << future.errorCode() + << " executing [" << ss.str() << "]" << std::endl; + return false; + } + + if (cb) + return future.setCallback( cb, data ); + + return true; +} + //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// diff --git a/hss/src/fdhss.cpp b/hss/src/fdhss.cpp index af93efd..df733dd 100755 --- a/hss/src/fdhss.cpp +++ b/hss/src/fdhss.cpp @@ -188,7 +188,6 @@ bool FDHss::init(hss_config_t * hss_config_p){ m_endpoint->serveThreaded(); Pistache::Address addrOss( Pistache::Ipv4::any(), Pistache::Port(Options::getossport()) ); - m_ossendpoint = new OssEndpoint(addrOss, &StatsHss::singleton(), &Logger::singleton().audit(), &Logger::singleton(), Options::getossfile()); m_ossendpoint->init(); m_ossendpoint->start(); @@ -418,6 +417,16 @@ s->dump(); } } +void FDHss::poppulate_IMSIs(const ImsiEntity &ie) +{ + m_dbobj.insertUserImsi(ie, NULL, NULL); +} + +void FDHss::remove_IMSI(const ImsiEntity &ie) +{ + m_dbobj.deleteUserImsi(ie, NULL, NULL); +} + //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// diff --git a/hss/src/portal_config.cpp b/hss/src/portal_config.cpp new file mode 100644 index 0000000..7ea23cf --- /dev/null +++ b/hss/src/portal_config.cpp @@ -0,0 +1,369 @@ +// Copyright 2020-present Open Networking Foundation +// +// SPDX-License-Identifier: Apache-2.0 + +#include +#include "rapidjson/document.h" +#include "rapidjson/writer.h" +#include "rapidjson/stringbuffer.h" +#include "rapidjson/filereadstream.h" +#include +#include +#include +#include "portal_config.h" + + +bool +local_compare_sub_rules(const sub_selection_rule *rule1, const sub_selection_rule *rule2) +{ + if(rule1->rule_priority < rule2->rule_priority) + return true; + return false; +} + +portalConfig * +parse_json_doc(RAPIDJSON_NAMESPACE::Document &doc) +{ + portalConfig *config = new (portalConfig); + + if(doc.HasMember("subscriber-selection-rules")) + { + for(uint32_t i=0; i< doc["subscriber-selection-rules"].Size();i++) + { + sub_selection_rule *sub_rule = new (sub_selection_rule); + std::cout<<"\tSubscriber selection rule "<keys = nullptr; + const RAPIDJSON_NAMESPACE::Value& subRuleSection = doc["subscriber-selection-rules"][i]; + if(subRuleSection.HasMember("priority")) + { + sub_rule->rule_priority = subRuleSection["priority"].GetInt(); + std::cout<<"\t\tkeys has priority "<rule_priority<imsi.is_valid = false; + key->plmn.is_valid = false; + key->apn.is_valid = false; + sub_rule->keys = key; + const RAPIDJSON_NAMESPACE::Value& ruleKeys = subRuleSection["keys"]; + if(ruleKeys.HasMember("imsi-range") && ruleKeys["imsi-range"].IsObject()) + { + std::cout<<"\t\t\tkeys has imsi-range Object "<imsi.is_valid = true; + key->imsi.from_imsi= imsiKeys["from"].GetInt64(); + key->imsi.to_imsi= imsiKeys["to"].GetInt64(); + } + if(ruleKeys.HasMember("serving-plmn") && ruleKeys["serving-plmn"].IsObject()) + { + std::cout<<"\t\t\tkeys has serving-plmn Object "<plmn.is_valid = true; + uint16_t mcc_dig_1, mcc_dig_2, mcc_dig_3; + uint16_t mnc_dig_1, mnc_dig_2, mnc_dig_3; + mcc_dig_1 = mcc/100; mcc = mcc % 100; + mcc_dig_2 = mcc/10; mcc = mcc %10; + mcc_dig_3 = mcc; + if(mnc > 99) + { + mnc_dig_1 = (mnc/100); + mnc_dig_2 = (mnc%100)/10; + mnc_dig_3 = mnc % 10; + } + else + { + mnc_dig_3 = 0xf; + mnc_dig_1 = mnc/10; + mnc_dig_2 = mnc % 10; + } + + key->plmn.plmn[0] = (mcc_dig_2 << 4) | (mcc_dig_1); + key->plmn.plmn[1] = (mnc_dig_1 << 4) | (mcc_dig_3); + key->plmn.plmn[2] = (mnc_dig_3 << 4) | (mnc_dig_2); + key->plmn.tac = plmnKeys["tac"].GetInt(); + } + if(ruleKeys.HasMember("requested-apn")) + { + key->apn.requested_apn = ruleKeys["requested-apn"].GetString(); + std::cout<<"\t\t\tkeys has requested-apn "<apn.requested_apn<apn.is_valid = true; + } + } + std::cout<<"\t\tSelected Profiles"<selected_apn_profile = subRuleSection["selected-apn-profile"].GetString(); + std::cout<<"\t\t\tselected-apn-profile found - "<selected_apn_profile<selected_user_plane_profile = subRuleSection["selected-user-plane-profile"].GetString(); + std::cout<<"\t\t\tselected-user-plane-profile found "<selected_user_plane_profile<selected_qos_profile = subRuleSection["selected-qos-profile"].GetString(); + std::cout<<"\t\t\tselected-qos-profile found - "<selected_qos_profile<selected_security_profile = subRuleSection["selected-security-profile"].GetString(); + std::cout<<"\t\t\tselected-security-profile found - "<selected_security_profile<selected_access_profile[acc] = accessProfile.GetString(); + std::cout<<"\t\t\tselected-access-profile - "<selected_access_profile[acc]<sub_sel_rules.push_back(sub_rule); + } + config->sub_sel_rules.sort(local_compare_sub_rules); + } + if(doc.HasMember("apn-profiles")) + { + const RAPIDJSON_NAMESPACE::Value& apnProfileSection = doc["apn-profiles"]; + for (RAPIDJSON_NAMESPACE::Value::ConstMemberIterator itr = apnProfileSection.MemberBegin(); itr != apnProfileSection.MemberEnd(); ++itr) + { + std::string key = itr->name.GetString(); + if(itr->value.IsObject()) + { + std::cout<<"\tAPN profile "<< key.c_str()<<" is Object"<apn_profile_name = key; + const RAPIDJSON_NAMESPACE::Value& apnSection = itr->value; + if(apnSection.HasMember("apn-name")) { + apn_prof->apn_name = apnSection["apn-name"].GetString(); + std::cout<<"\t\tAPN name["<apn_name<<"]"<apn_name_length = apn_prof->apn_name.length(); + std::cout<<"\t\tAPN name after encode ["<apn_name<<"]"<apn_usage_type = usage; + } + if(apnSection.HasMember("network")) { + apn_prof->apn_net_cap = apnSection["network"].GetString(); + std::cout<<"\t\tNetwork type "<apn_net_cap<gx_enabled = gx_enabled; + } + if(apnSection.HasMember("mtu")) { + uint16_t mtu = apnSection["mtu"].GetInt(); + std::cout<<"\t\tAPN has mtu "<mtu = mtu; + } + if(apnSection.HasMember("dns_primary")) { + const char *temp = apnSection["dns_primary"].GetString(); + std::cout<<"\t\tAPN has dns_primary "<dns_primary = temp_i.s_addr; + } + if(apnSection.HasMember("dns_secondary")) { + const char *temp = apnSection["dns_secondary"].GetString(); + std::cout<<"\t\tAPN has dns_secondary "<dns_secondary = temp_i.s_addr; + } + config->apn_profile_list.push_back(apn_prof); + std::cout<name.GetString(); + user_plane_profile *user_plane = new (user_plane_profile); + user_plane->upf_addr = 0; + const RAPIDJSON_NAMESPACE::Value& userPlaneSection = itr->value; + user_plane->user_plane_profile_name = key; + if(userPlaneSection.HasMember("user-plane")) + { + user_plane->user_plane_service = userPlaneSection["user-plane"].GetString(); + std::cout<<"\tUser Plane - "<user_plane_service<user_plane_list.push_back(user_plane); + } + } + if(doc.HasMember("qos-profiles")) + { + const RAPIDJSON_NAMESPACE::Value& qosProfileSection = doc["qos-profiles"]; + for (RAPIDJSON_NAMESPACE::Value::ConstMemberIterator itr = qosProfileSection.MemberBegin(); itr != qosProfileSection.MemberEnd(); ++itr) + { + qos_profile *qos_prof = new (qos_profile); + std::string key = itr->name.GetString(); + qos_prof->qos_profile_name = key; + std::cout<<"\tQoS profile - "<value; + qos_prof->apn_ambr_ul = qosPlaneSection["apn-ambr"][0].GetInt64(); + qos_prof->apn_ambr_dl = qosPlaneSection["apn-ambr"][1].GetInt64(); + qos_prof->qci = qosPlaneSection["qci"].GetInt64(); + std::cout<<" qci "<qci<priority = arpProfileSection["priority"].GetInt64(); + qos_prof->pre_empt_capability = arpProfileSection["pre-emption-capability"].GetInt64(); + qos_prof->pre_empt_vulnerability = arpProfileSection["pre-emption-vulnerability"].GetInt64(); + std::cout<<"\t\tQoS apn ambr uplink - "<apn_ambr_ul<apn_ambr_dl<qci<priority<pre_empt_capability<pre_empt_vulnerability<qos_profile_list.push_back(qos_prof); + } + } + if(doc.HasMember("security-profiles")) + { + const RAPIDJSON_NAMESPACE::Value& securityProfileSection = doc["security-profiles"]; + for (RAPIDJSON_NAMESPACE::Value::ConstMemberIterator itr = securityProfileSection.MemberBegin(); itr != securityProfileSection.MemberEnd(); ++itr) + { + security_profile *profile = new (security_profile); + profile->name = itr->name.GetString(); + std::cout<<"\tSecurity profile - "<name<value; + profile->key = secSection["key"].GetString(); + profile->opc = secSection["opc"].GetString(); + profile->sqn = secSection["sqn"].GetInt64(); + std::cout<<"Security Profile Name - "<name + <<" Opc - "<opc <<" key - "<key + <<" sqn - "<sqn<security_profile_list.push_back(profile); + } + } + if(doc.HasMember("access-profiles")) + { + const RAPIDJSON_NAMESPACE::Value& accessProfileSection = doc["access-profiles"]; + for (RAPIDJSON_NAMESPACE::Value::ConstMemberIterator itr = accessProfileSection.MemberBegin(); itr != accessProfileSection.MemberEnd(); ++itr) + { + std::string key = itr->name.GetString(); + std::cout<<"\tAccess profile - "<access_profile_name = key; + config->access_profile_list.push_back(access_prof); + } + } + return config; +} + +newPortalConfig * +parse_hss_json_doc(RAPIDJSON_NAMESPACE::Document &doc) +{ + newPortalConfig *config = new (newPortalConfig); + + if(doc.HasMember("start-imsi")) + { + config->from_imsi= doc["start-imsi"].GetInt64(); + } + + if(doc.HasMember("end-imsi")) + { + config->to_imsi= doc["start-imsi"].GetInt64(); + } + + if(doc.HasMember("Opc")) + { + config->opc = doc["Opc"].GetString(); + } + + if(doc.HasMember("Key")) + { + config->key = doc["Key"].GetString(); + } + + if(doc.HasMember("Sqn")) + { + config->sqn = doc["Sqn"].GetInt64(); + } + + if(doc.HasMember("ambr-dl")) + { + config->apn_ambr_dl = doc["ambr-dl"].GetInt(); + } + + if(doc.HasMember("ambr-up")) + { + config->apn_ambr_ul = doc["ambr-up"].GetInt(); + } + + if(doc.HasMember("qci")) + { + config->qci = doc["qci"].GetInt(); + } + + if(doc.HasMember("arp")) + { + config->arp= doc["arp"].GetInt(); + } + + if(doc.HasMember("apn-profiles")) + { + const RAPIDJSON_NAMESPACE::Value& apnProfileSection = doc["apn-profiles"]; + for (RAPIDJSON_NAMESPACE::Value::ConstMemberIterator itr = apnProfileSection.MemberBegin(); itr != apnProfileSection.MemberEnd(); ++itr) + { + std::string key = itr->name.GetString(); + if(itr->value.IsObject()) + { + std::cout<<"\tAPN profile "<< key.c_str()<<" is Object"<apn_profile_name = key; + const RAPIDJSON_NAMESPACE::Value& apnSection = itr->value; + if(apnSection.HasMember("apn-name")) { + apn_prof->apn_name = apnSection["apn-name"].GetString(); + std::cout<<"\t\tAPN name["<apn_name<<"]"<apn_name_length = apn_prof->apn_name.length(); + std::cout<<"\t\tAPN name after encode ["<apn_name<<"]"<apn_profile_list.push_back(apn_prof); + std::cout< +#include "portal_config.h" void RestHandler::onRequest(const Pistache::Http::Request& request, Pistache::Http::ResponseWriter response) { - std::cout << request.resource() << std::endl; - std::cout << request.method() << std::endl; - std::cout << request.body() << std::endl; + static bool needConfig = true; + if (request.resource() == "/v2/config-check") { + if (needConfig == true) { + response.send(Pistache::Http::Code::Not_Found); + needConfig = false; + } else { + response.send(Pistache::Http::Code::Ok); + } + } else if (request.resource() == "/v2/config/imsis") { + // Post handler + std::cout<<"v2 config imsis resource "<from_imsi; imsi <= config->to_imsi; imsi++ ) + { + ImsiEntity data; + data.imsi = std::to_string(imsi); data.imsi_pres = true; + fdHss.remove_IMSI(data); + } + return; + } + + for (uint64_t imsi = config->from_imsi; imsi <= config->to_imsi; imsi++ ) + { + ImsiEntity data; + std::cout<<"\n\nIMSI "<opc; data.opc_pres = true; + data.key = config->key; data.key_pres = true; + data.sqn = config->sqn; data.sqn_pres = true; + data.rand = "2683b376d1056746de3b254012908e0e"; data.rand_pres = true; + data.msisdn = 1122334456; data.msisdn_pres = true; + data.access_restriction = 41; data.access_restriction_pres = true; + data.mmeidentity_idmmeidentity = 3; data.mmeidentity_idmmeidentity_pres = true; + + data.supported_features = "{\"Supported-Features\":{\"Vendor-Id\": 10415, \"Feature-List-ID\": 2, \"Feature-List\": 134217728}}"; + data.supported_features_pres = true; + + { + RAPIDJSON_NAMESPACE::Document jsonDoc; + jsonDoc.SetObject(); + RAPIDJSON_NAMESPACE::Document::AllocatorType& allocator = jsonDoc.GetAllocator(); + + RAPIDJSON_NAMESPACE::Value objValue; + objValue.SetObject(); + objValue.AddMember("Access-Restriction-Data", 41, allocator); + objValue.AddMember("Subscriber-Status", 0, allocator); + objValue.AddMember("Network-Access-Mode", 2, allocator); + objValue.AddMember("Subscribed-Periodic-RAU-TAU-Timer", 0, allocator); + objValue.AddMember("MSISDN", 0x1122334458, allocator); - if (request.resource() == "/imsis") - { + { + RAPIDJSON_NAMESPACE::Value objAmbr; + objAmbr.SetObject(); + objAmbr.AddMember("Max-Requested-Bandwidth-UL", config->apn_ambr_ul, allocator); + objAmbr.AddMember("Max-Requested-Bandwidth-DL", config->apn_ambr_dl, allocator); + objValue.AddMember("AMBR", objAmbr, allocator); + } + + { + RAPIDJSON_NAMESPACE::Value zoneCode(RAPIDJSON_NAMESPACE::kArrayType); + zoneCode.PushBack("0x0123", allocator); + zoneCode.PushBack("0x4567", allocator); + zoneCode.PushBack("0x89AB", allocator); + zoneCode.PushBack("0xCDEF", allocator); + zoneCode.PushBack("0x1234", allocator); + zoneCode.PushBack("0x5678", allocator); + zoneCode.PushBack("0x9ABC", allocator); + zoneCode.PushBack("0xDEF0", allocator); + zoneCode.PushBack("0x2345", allocator); + zoneCode.PushBack("0x6789", allocator); + objValue.AddMember("Regional-Subscription-Zone-Code", zoneCode, allocator); + } + + for (std::list::iterator it=config->apn_profile_list.begin(); it!=config->apn_profile_list.end(); ++it) + { + apn_profile *apn_prof = *it; + RAPIDJSON_NAMESPACE::Value objApnProfile; + objApnProfile.SetObject(); + objApnProfile.AddMember("Context-Identifier",0, allocator); + objApnProfile.AddMember("All-APN-Configurations-Included-Indicator",0, allocator); + { + RAPIDJSON_NAMESPACE::Value objApnConf; + objApnConf.SetObject(); + objApnConf.AddMember("Context-Identifier",0, allocator); + objApnConf.AddMember("PDN-Type",0, allocator); + objApnConf.AddMember("Service-Selection", RAPIDJSON_NAMESPACE::Value(apn_prof->apn_name.c_str(), allocator), allocator); + objApnConf.AddMember("PDN-GW-AllocatorType", 0, allocator); + + RAPIDJSON_NAMESPACE::Value staticIp(RAPIDJSON_NAMESPACE::kArrayType); + staticIp.PushBack("0.0.0.0", allocator); + objApnConf.AddMember("Served-Party-IP-Address", staticIp, allocator); + + // AMBR + { + RAPIDJSON_NAMESPACE::Value objAmbr; + objAmbr.SetObject(); + objAmbr.AddMember("Max-Requested-Bandwidth-UL", config->apn_ambr_ul, allocator); + objAmbr.AddMember("Max-Requested-Bandwidth-DL", config->apn_ambr_dl, allocator); + objApnConf.AddMember("AMBR", objAmbr, allocator); + } + + //EPS QoS + { + RAPIDJSON_NAMESPACE::Value objBQos; + objBQos.SetObject(); + objBQos.AddMember("QoS-Class-Identifier", config->qci, allocator); + { + RAPIDJSON_NAMESPACE::Value objArp; + objArp.SetObject(); + objArp.AddMember("Priority-Level", 1, allocator); + objArp.AddMember("Pre-emption-Capability", 1, allocator); + objArp.AddMember("Pre-emption-Vulnerability", 1, allocator); + objBQos.AddMember("Allocation-Retention-Priority", objArp, allocator); + } + objApnConf.AddMember("EPS-Subscribed-QoS-Profile", objBQos, allocator); + } + + //MIP + { + RAPIDJSON_NAMESPACE::Value objMip; + objMip.SetObject(); + RAPIDJSON_NAMESPACE::Value addr(RAPIDJSON_NAMESPACE::kArrayType); + addr.PushBack("0.0.0.0", allocator); + objMip.AddMember("MIP-Home-Agent-Address", addr, allocator); + objApnConf.AddMember("MIP6-Agent-Info", objMip, allocator); + } + + objApnProfile.AddMember("APN-Configuration", objApnConf, allocator); + } + objValue.AddMember("APN-Configuration-Profile", objApnProfile, allocator); + } + + jsonDoc.AddMember("Subscription-Data", objValue, allocator); + RAPIDJSON_NAMESPACE::StringBuffer strbuf; + RAPIDJSON_NAMESPACE::Writer writer(strbuf); + jsonDoc.Accept(writer); + const char *jsonString = strbuf.GetString(); + std::cout<<"jsonString "< ::iterator it=config->sub_sel_rules.begin(); it != config->sub_sel_rules.end(); ++it) + { + sub_selection_rule *rule = *it; + sub_selection_keys *keys = rule->keys; + if(keys->imsi.is_valid == false) { + continue; + } + security_profile *sec_prof = config->get_security_profile(rule->selected_security_profile); + if(sec_prof == NULL) { + continue; + } + + qos_profile *qos_prof = config->get_qos_profile(rule->selected_qos_profile); + if(qos_prof == NULL) { + continue; + } + + apn_profile *apn_prof = config->get_apn_profile(rule->selected_apn_profile); + if(apn_prof == NULL) { + continue; + } + + for(uint64_t imsi = keys->imsi.from_imsi; imsi <= keys->imsi.to_imsi; imsi++) + { + ImsiEntity data; + std::cout<<"\n\nIMSI "<opc; data.opc_pres = true; + data.key = sec_prof->key; data.key_pres = true; + data.sqn = sec_prof->sqn; data.sqn_pres = true; + data.rand = "2683b376d1056746de3b254012908e0e"; data.rand_pres = true; + data.msisdn = 1122334456; data.msisdn_pres = true; + data.access_restriction = 41; data.access_restriction_pres = true; + data.mmeidentity_idmmeidentity = 3; data.mmeidentity_idmmeidentity_pres = true; + + data.supported_features = "{\"Supported-Features\":{\"Vendor-Id\": 10415, \"Feature-List-ID\": 2, \"Feature-List\": 134217728}}"; + data.supported_features_pres = true; + + { + RAPIDJSON_NAMESPACE::Document jsonDoc; + jsonDoc.SetObject(); + RAPIDJSON_NAMESPACE::Document::AllocatorType& allocator = jsonDoc.GetAllocator(); + + RAPIDJSON_NAMESPACE::Value objValue; + objValue.SetObject(); + objValue.AddMember("Access-Restriction-Data", 41, allocator); + objValue.AddMember("Subscriber-Status", 0, allocator); + objValue.AddMember("Network-Access-Mode", 2, allocator); + objValue.AddMember("Subscribed-Periodic-RAU-TAU-Timer", 0, allocator); + objValue.AddMember("MSISDN", 0x1122334458, allocator); + + { + RAPIDJSON_NAMESPACE::Value objAmbr; + objAmbr.SetObject(); + objAmbr.AddMember("Max-Requested-Bandwidth-UL", qos_prof->apn_ambr_ul, allocator); + objAmbr.AddMember("Max-Requested-Bandwidth-DL", qos_prof->apn_ambr_dl, allocator); + objValue.AddMember("AMBR", objAmbr, allocator); + } + + { + RAPIDJSON_NAMESPACE::Value zoneCode(RAPIDJSON_NAMESPACE::kArrayType); + zoneCode.PushBack("0x0123", allocator); + zoneCode.PushBack("0x4567", allocator); + zoneCode.PushBack("0x89AB", allocator); + zoneCode.PushBack("0xCDEF", allocator); + zoneCode.PushBack("0x1234", allocator); + zoneCode.PushBack("0x5678", allocator); + zoneCode.PushBack("0x9ABC", allocator); + zoneCode.PushBack("0xDEF0", allocator); + zoneCode.PushBack("0x2345", allocator); + zoneCode.PushBack("0x6789", allocator); + objValue.AddMember("Regional-Subscription-Zone-Code", zoneCode, allocator); + } + + { + RAPIDJSON_NAMESPACE::Value objApnProfile; + objApnProfile.SetObject(); + objApnProfile.AddMember("Context-Identifier",0, allocator); + objApnProfile.AddMember("All-APN-Configurations-Included-Indicator",0, allocator); + { + RAPIDJSON_NAMESPACE::Value objApnConf; + objApnConf.SetObject(); + objApnConf.AddMember("Context-Identifier",0, allocator); + objApnConf.AddMember("PDN-Type",0, allocator); + objApnConf.AddMember("Service-Selection", RAPIDJSON_NAMESPACE::Value(apn_prof->apn_name.c_str(), allocator), allocator); + objApnConf.AddMember("PDN-GW-AllocatorType", 0, allocator); + + RAPIDJSON_NAMESPACE::Value staticIp(RAPIDJSON_NAMESPACE::kArrayType); + staticIp.PushBack("0.0.0.0", allocator); + objApnConf.AddMember("Served-Party-IP-Address", staticIp, allocator); + + // AMBR + { + RAPIDJSON_NAMESPACE::Value objAmbr; + objAmbr.SetObject(); + objAmbr.AddMember("Max-Requested-Bandwidth-UL", qos_prof->apn_ambr_ul, allocator); + objAmbr.AddMember("Max-Requested-Bandwidth-DL", qos_prof->apn_ambr_dl, allocator); + objApnConf.AddMember("AMBR", objAmbr, allocator); + } + + //EPS QoS + { + RAPIDJSON_NAMESPACE::Value objBQos; + objBQos.SetObject(); + objBQos.AddMember("QoS-Class-Identifier", qos_prof->qci, allocator); + { + RAPIDJSON_NAMESPACE::Value objArp; + objArp.SetObject(); + objArp.AddMember("Priority-Level", qos_prof->priority, allocator); + objArp.AddMember("Pre-emption-Capability", qos_prof->pre_empt_capability, allocator); + objArp.AddMember("Pre-emption-Vulnerability", qos_prof->pre_empt_vulnerability, allocator); + objBQos.AddMember("Allocation-Retention-Priority", objArp, allocator); + } + objApnConf.AddMember("EPS-Subscribed-QoS-Profile", objBQos, allocator); + } + + //MIP + { + RAPIDJSON_NAMESPACE::Value objMip; + objMip.SetObject(); + RAPIDJSON_NAMESPACE::Value addr(RAPIDJSON_NAMESPACE::kArrayType); + addr.PushBack("0.0.0.0", allocator); + objMip.AddMember("MIP-Home-Agent-Address", addr, allocator); + objApnConf.AddMember("MIP6-Agent-Info", objMip, allocator); + } + + objApnProfile.AddMember("APN-Configuration", objApnConf, allocator); + } + objValue.AddMember("APN-Configuration-Profile", objApnProfile, allocator); + } + + jsonDoc.AddMember("Subscription-Data", objValue, allocator); + RAPIDJSON_NAMESPACE::StringBuffer strbuf; + RAPIDJSON_NAMESPACE::Writer writer(strbuf); + jsonDoc.Accept(writer); + const char *jsonString = strbuf.GetString(); + std::cout<<"jsonString "< 0) && + fdJsonAddAvps(m_orig_info.supported_features.c_str(), m_ans.getMsg(), &s6as6d::display_error_message) != 0) + { + std::cout<<"Error in adding supported features\n"; + } + m_nextphase = ULRSTATE_PHASE3; } diff --git a/hssgtw/include/db.h b/hssgtw/include/db.h index a8f1925..6c91347 100644 --- a/hssgtw/include/db.h +++ b/hssgtw/include/db.h @@ -108,6 +108,7 @@ class ImsiEntity rfsp_index = 0; sqn = 0; subscription_data = ""; + supported_features = ""; ue_reachability = 0; urrp_mme = 0; user_identifier = ""; @@ -165,6 +166,7 @@ class ImsiEntity PARSE_INT32(document, rfsp_index); PARSE_INT32(document, sqn); PARSE_STRING(document, subscription_data); + PARSE_STRING(document, supported_features); PARSE_INT32(document, ue_reachability); PARSE_INT32(document, urrp_mme); PARSE_STRING(document, user_identifier); @@ -194,6 +196,7 @@ class ImsiEntity int32_t rfsp_index; bool rfsp_index_pres; int32_t sqn; bool sqn_pres; std::string subscription_data; bool subscription_data_pres; + std::string supported_features; bool supported_features_pres; int32_t ue_reachability; bool ue_reachability_pres; int32_t urrp_mme; bool urrp_mme_pres; std::string user_identifier; bool user_identifier_pres; diff --git a/hssgtw/src/db.cpp b/hssgtw/src/db.cpp index e61b3e0..62bdde3 100644 --- a/hssgtw/src/db.cpp +++ b/hssgtw/src/db.cpp @@ -79,7 +79,7 @@ bool DB::insertUserImsi( const ImsiEntity &ie ) << "imsi,access_restriction,idmmeidentity,imei,imei_sv,key," << "lipa_permissions,mme_cap,mmehost,mmeidentity_idmmeidentity," << "mmerealm,ms_ps_status,msisdn,niddvalidity,nir_dest_host," - << "nir_dest_realm,opc,pgw_id,rand,rfsp_index,sqn,subscription_data," + << "nir_dest_realm,opc,pgw_id,rand,rfsp_index,sqn,subscription_data,supported_features" << "ue_reachability,urrp_mme,user_identifier,visited_plmnid" << ") VALUES ("; ADD_VALUE_STRING(ss, ie, imsi, ","); @@ -104,6 +104,7 @@ bool DB::insertUserImsi( const ImsiEntity &ie ) ADD_VALUE_INT(ss, ie, rfsp_index, ","); ADD_VALUE_INT(ss, ie, sqn, ","); ADD_VALUE_STRING(ss, ie, subscription_data, ","); + ADD_VALUE_STRING(ss, ie, supported_features, ","); ADD_VALUE_INT(ss, ie, ue_reachability, ","); ADD_VALUE_INT(ss, ie, urrp_mme, ","); ADD_VALUE_STRING(ss, ie, user_identifier, ","); @@ -159,6 +160,7 @@ bool DB::updateUserImsi( const ImsiEntity &ie ) ADD_UPDATE_INT(ss, ie, rfsp_index, cnt); ADD_UPDATE_INT(ss, ie, sqn, cnt); ADD_UPDATE_STRING(ss, ie, subscription_data, cnt); + ADD_UPDATE_STRING(ss, ie, supported_features, cnt); ADD_UPDATE_INT(ss, ie, ue_reachability, cnt); ADD_UPDATE_INT(ss, ie, urrp_mme, cnt); ADD_UPDATE_STRING(ss, ie, user_identifier, cnt); diff --git a/install_builddeps.sh b/install_builddeps.sh index 12e8f02..cec2a39 100755 --- a/install_builddeps.sh +++ b/install_builddeps.sh @@ -79,12 +79,12 @@ install_rapidjson() { install_pistache() { cd /tmp - wget https://github.com/Kitware/CMake/releases/download/v3.18.0/cmake-3.18.0-Linux-x86_64.tar.gz - tar -zxvf cmake-3.18.0-Linux-x86_64.tar.gz + wget https://github.com/Kitware/CMake/releases/download/v3.18.0/cmake-3.18.0-Linux-x86_64.tar.gz + tar -zxvf cmake-3.18.0-Linux-x86_64.tar.gz echo "Installing pistache" cd $DEPS_DIR/pistache - echo $PWD - patch -p1 -g1 < ../../patches/pistache.patch.1.txt + echo $PWD + patch -p1 < ../../patches/pistache.patch.1.txt mkdir build && cd build /tmp/cmake-3.18.0-Linux-x86_64/bin/cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release ../ make -j $CPUS