Commit f3616257 authored by Tien-Thinh Nguyen's avatar Tien-Thinh Nguyen

apply simple format

parent 5d4921e4
......@@ -4,7 +4,7 @@ AMF =
INSTANCE_ID = 10;
PID_DIRECTORY = "/var/run";
######################################################################## NG SETUP RESPONSE IEs ############################################################
AMF_NAME = "bupt-amf";
AMF_NAME = "amf";
GUAMI:{MCC = "208"; MNC = "95"; RegionID = "128"; AMFSetID = "1"; AMFPointer = "1"}
ServedGUAMIList = (
{MCC = "208"; MNC = "95"; RegionID = "10"; AMFSetID = "1"; AMFPointer = "0"}, #48bits <MCC><MNC><RegionID><AMFSetID><AMFPointer>
......
......@@ -46,155 +46,167 @@ using namespace amf_application;
using namespace config;
extern void print_buffer(const std::string app, const std::string commit, uint8_t *buf, int len);
extern amf_app * amf_app_inst;
extern itti_mw * itti_inst;
amf_n2 * amf_n2_inst = nullptr;
amf_n1 * amf_n1_inst = nullptr;
amf_n11 * amf_n11_inst = nullptr;
extern amf_app *amf_app_inst;
extern itti_mw *itti_inst;
amf_n2 *amf_n2_inst = nullptr;
amf_n1 *amf_n1_inst = nullptr;
amf_n11 *amf_n11_inst = nullptr;
extern amf_config amf_cfg;
extern statistics stacs;
void amf_app_task(void*);
uint32_t golbal_tmsi = 1;
amf_app::amf_app(const amf_config &amf_cfg){
Logger::amf_app().startup("Creating amf application functionality layer");
if(itti_inst->create_task(TASK_AMF_APP, amf_app_task, nullptr)){
Logger::amf_app().error( "Cannot create task TASK_AMF_APP" );
throw std::runtime_error( "Cannot create task TASK_AMF_APP" );
//------------------------------------------------------------------------------
amf_app::amf_app(const amf_config &amf_cfg) {
Logger::amf_app().startup("Creating AMF application functionality layer");
if (itti_inst->create_task(TASK_AMF_APP, amf_app_task, nullptr)) {
Logger::amf_app().error("Cannot create task TASK_AMF_APP");
throw std::runtime_error("Cannot create task TASK_AMF_APP");
}
try{
amf_n2_inst = new amf_n2(std::string(inet_ntoa(amf_cfg.n2.addr4)),amf_cfg.n2.port);
}catch(std::exception& e){
Logger::amf_app().error( "Cannot create amf n2 interface: %s", e.what() );
try {
amf_n2_inst = new amf_n2(std::string(inet_ntoa(amf_cfg.n2.addr4)), amf_cfg.n2.port);
} catch (std::exception &e) {
Logger::amf_app().error("Cannot create N2 interface: %s", e.what());
throw;
}
try{
try {
amf_n1_inst = new amf_n1();
}catch(std::exception& e){
Logger::amf_app().error( "Cannot create amf n1 interface: %s", e.what() );
} catch (std::exception &e) {
Logger::amf_app().error("Cannot create N1 interface: %s", e.what());
}
try{
try {
amf_n11_inst = new amf_n11();
}catch(std::exception& e){
Logger::amf_app().error( "Cannot create amf n11 interface: %s", e.what() );
} catch (std::exception &e) {
Logger::amf_app().error("Cannot create N11 interface: %s", e.what());
}
timer_id_t tid = itti_inst->timer_setup(amf_cfg.statistics_interval,0,TASK_AMF_APP,TASK_AMF_APP_PERIODIC_STATISTICS,0);
Logger::amf_app().startup( "Started timer(%d)", tid);
timer_id_t tid = itti_inst->timer_setup(amf_cfg.statistics_interval, 0, TASK_AMF_APP, TASK_AMF_APP_PERIODIC_STATISTICS, 0);
Logger::amf_app().startup("Started timer(%d)", tid);
}
void amf_app::allRegistredModulesInit(const amf_modules & modules){
Logger::amf_app().info("Initiating all registred modules");
//------------------------------------------------------------------------------
void amf_app::allRegistredModulesInit(const amf_modules &modules) {
Logger::amf_app().info("Initiating all registered modules");
}
void amf_app_task(void*){
//------------------------------------------------------------------------------
void amf_app_task(void*) {
const task_id_t task_id = TASK_AMF_APP;
itti_inst->notify_task_ready(task_id);
do {
std::shared_ptr<itti_msg> shared_msg = itti_inst->receive_msg(task_id);
auto *msg = shared_msg.get();
timer_id_t tid;
switch(msg->msg_type){
case NAS_SIG_ESTAB_REQ:{
switch (msg->msg_type) {
case NAS_SIG_ESTAB_REQ: {
Logger::amf_app().debug("Received NAS_SIG_ESTAB_REQ");
itti_nas_signalling_establishment_request *m = dynamic_cast<itti_nas_signalling_establishment_request*>(msg);
amf_app_inst->handle_itti_message(ref(*m));
}break;
}
break;
case N1N2_MESSAGE_TRANSFER_REQ:{
case N1N2_MESSAGE_TRANSFER_REQ: {
Logger::amf_app().debug("Received N1N2_MESSAGE_TRANSFER_REQ");
itti_n1n2_message_transfer_request *m = dynamic_cast<itti_n1n2_message_transfer_request*>(msg);
amf_app_inst->handle_itti_message(ref(*m));
}break;
}
break;
case TIME_OUT:
if (itti_msg_timeout* to = dynamic_cast<itti_msg_timeout*>(msg)) {
switch(to->arg1_user){
if (itti_msg_timeout *to = dynamic_cast<itti_msg_timeout*>(msg)) {
switch (to->arg1_user) {
case TASK_AMF_APP_PERIODIC_STATISTICS:
tid = itti_inst->timer_setup(amf_cfg.statistics_interval,0,TASK_AMF_APP,TASK_AMF_APP_PERIODIC_STATISTICS,0);
//Logger::amf_app().info("statistics(ready to be implemented)");
tid = itti_inst->timer_setup(amf_cfg.statistics_interval, 0, TASK_AMF_APP, TASK_AMF_APP_PERIODIC_STATISTICS, 0);
stacs.display();
break;
default:
Logger::amf_app().info( "no handler for timer(%d) with arg1_user(%d) ", to->timer_id, to->arg1_user);
Logger::amf_app().info("no handler for timer(%d) with arg1_user(%d) ", to->timer_id, to->arg1_user);
}
}
break;
default:
Logger::amf_app().info( "no handler for msg type %d", msg->msg_type);
Logger::amf_app().info("no handler for msg type %d", msg->msg_type);
}
}while(true);
} while (true);
}
long amf_app::generate_amf_ue_ngap_id(){
//------------------------------------------------------------------------------
long amf_app::generate_amf_ue_ngap_id() {
long tmp = 0;
tmp = __sync_fetch_and_add(&amf_app_ue_ngap_id_generator,1);
tmp = __sync_fetch_and_add(&amf_app_ue_ngap_id_generator, 1);
return tmp & 0xffffffffff;
}
/****************************** context management **************************/
bool amf_app::is_amf_ue_id_2_ue_context(const long & amf_ue_ngap_id) const {
//------------------------------------------------------------------------------
bool amf_app::is_amf_ue_id_2_ue_context(const long &amf_ue_ngap_id) const {
std::shared_lock lock(m_amf_ue_ngap_id2ue_ctx);
return bool{amf_ue_ngap_id2ue_ctx.count(amf_ue_ngap_id) > 0};
return bool { amf_ue_ngap_id2ue_ctx.count(amf_ue_ngap_id) > 0 };
}
std::shared_ptr<ue_context> amf_app::amf_ue_id_2_ue_context(const long & amf_ue_ngap_id) const {
//------------------------------------------------------------------------------
std::shared_ptr<ue_context> amf_app::amf_ue_id_2_ue_context(const long &amf_ue_ngap_id) const {
std::shared_lock lock(m_amf_ue_ngap_id2ue_ctx);
return amf_ue_ngap_id2ue_ctx.at(amf_ue_ngap_id);
}
void amf_app::set_amf_ue_ngap_id_2_ue_context(const long & amf_ue_ngap_id, std::shared_ptr<ue_context> uc){
//------------------------------------------------------------------------------
void amf_app::set_amf_ue_ngap_id_2_ue_context(const long &amf_ue_ngap_id, std::shared_ptr<ue_context> uc) {
std::shared_lock lock(m_amf_ue_ngap_id2ue_ctx);
amf_ue_ngap_id2ue_ctx[amf_ue_ngap_id] = uc;
}
bool amf_app::is_ran_amf_id_2_ue_context(const string & ue_context_key) const {
//------------------------------------------------------------------------------
bool amf_app::is_ran_amf_id_2_ue_context(const string &ue_context_key) const {
std::shared_lock lock(m_ue_ctx_key);
return bool{ue_ctx_key.count(ue_context_key) > 0};
return bool { ue_ctx_key.count(ue_context_key) > 0 };
}
std::shared_ptr<ue_context> amf_app::ran_amf_id_2_ue_context(const string & ue_context_key) const{
//------------------------------------------------------------------------------
std::shared_ptr<ue_context> amf_app::ran_amf_id_2_ue_context(const string &ue_context_key) const {
std::shared_lock lock(m_ue_ctx_key);
return ue_ctx_key.at(ue_context_key);
}
void amf_app::set_ran_amf_id_2_ue_context(const string & ue_context_key, std::shared_ptr<ue_context> uc){
//------------------------------------------------------------------------------
void amf_app::set_ran_amf_id_2_ue_context(const string &ue_context_key, std::shared_ptr<ue_context> uc) {
std::shared_lock lock(m_ue_ctx_key);
ue_ctx_key[ue_context_key] = uc;
}
/****************************** itti handlers *******************************/
void amf_app::handle_itti_message(itti_n1n2_message_transfer_request & itti_msg){
// ITTI handlers
//------------------------------------------------------------------------------
void amf_app::handle_itti_message(itti_n1n2_message_transfer_request &itti_msg) {
//1. encode DL NAS TRANSPORT message(NAS message)
DLNASTransport * dl = new DLNASTransport();
DLNASTransport *dl = new DLNASTransport();
dl->setHeader(PLAIN_5GS_MSG);
dl->setPayload_Container_Type(N1_SM_INFORMATION);
dl->setPayload_Container((uint8_t*)bdata(itti_msg.n1sm), blength(itti_msg.n1sm));
dl->setPayload_Container((uint8_t*) bdata(itti_msg.n1sm), blength(itti_msg.n1sm));
dl->setPDUSessionId(itti_msg.pdu_session_id);
uint8_t nas[1024];
int encoded_size = dl->encode2buffer(nas, 1024);
print_buffer("amf_app", "n1n2 transfer", nas, encoded_size);
bstring dl_nas = blk2bstr(nas,encoded_size);
bstring dl_nas = blk2bstr(nas, encoded_size);
itti_downlink_nas_transfer * dl_msg = new itti_downlink_nas_transfer(TASK_AMF_APP, TASK_AMF_N1);
itti_downlink_nas_transfer *dl_msg = new itti_downlink_nas_transfer(TASK_AMF_APP, TASK_AMF_N1);
dl_msg->dl_nas = dl_nas;
if(!itti_msg.is_n2sm_set){
if (!itti_msg.is_n2sm_set) {
dl_msg->is_n2sm_set = false;
}else{
} else {
dl_msg->n2sm = itti_msg.n2sm;
dl_msg->pdu_session_id = itti_msg.pdu_session_id;
dl_msg->is_n2sm_set = true;
}
dl_msg->amf_ue_ngap_id = amf_n1_inst->supi2amfId.at(itti_msg.supi);
dl_msg->ran_ue_ngap_id = amf_n1_inst->supi2ranId.at(itti_msg.supi);
std::shared_ptr<itti_downlink_nas_transfer> i = std::shared_ptr<itti_downlink_nas_transfer>(dl_msg);
std::shared_ptr<itti_downlink_nas_transfer> i = std::shared_ptr < itti_downlink_nas_transfer > (dl_msg);
int ret = itti_inst->send_msg(i);
if (0 != ret) {
Logger::amf_app().error( "Could not send ITTI message %s to task TASK_AMF_N1", i->get_msg_name());
Logger::amf_app().error("Could not send ITTI message %s to task TASK_AMF_N1", i->get_msg_name());
}
}
void amf_app::handle_itti_message(itti_nas_signalling_establishment_request & itti_msg){
//------------------------------------------------------------------------------
void amf_app::handle_itti_message(itti_nas_signalling_establishment_request &itti_msg) {
//1. generate amf_ue_ngap_id
//2. establish ue_context associated with amf_ue_ngap_id
//3. store ue-reated core information
......@@ -203,39 +215,40 @@ void amf_app::handle_itti_message(itti_nas_signalling_establishment_request & it
std::shared_ptr<ue_context> uc;
//check ue context with 5g-s-tmsi
if(amf_ue_ngap_id = itti_msg.amf_ue_ngap_id == -1){
if (amf_ue_ngap_id = itti_msg.amf_ue_ngap_id == -1) {
amf_ue_ngap_id = generate_amf_ue_ngap_id();
}
string ue_context_key = "app_ue_ranid_"+to_string(itti_msg.ran_ue_ngap_id)+":amfid_"+to_string(amf_ue_ngap_id);
string ue_context_key = "app_ue_ranid_" + to_string(itti_msg.ran_ue_ngap_id) + ":amfid_" + to_string(amf_ue_ngap_id);
//if(!is_amf_ue_id_2_ue_context(amf_ue_ngap_id)){
if(!is_ran_amf_id_2_ue_context(ue_context_key)){
if (!is_ran_amf_id_2_ue_context(ue_context_key)) {
Logger::amf_app().debug("no existed ue_context, Create one with ran_amf_id(%s)", ue_context_key.c_str());
uc = std::shared_ptr<ue_context>(new ue_context());
uc = std::shared_ptr < ue_context > (new ue_context());
//set_amf_ue_ngap_id_2_ue_context(amf_ue_ngap_id, uc);
set_ran_amf_id_2_ue_context(ue_context_key, uc);
}
if(uc.get() == nullptr){
if (uc.get() == nullptr) {
Logger::amf_app().error("Failed to create ue_context with ran_amf_id(%s)", ue_context_key.c_str());
}else{
} else {
uc.get()->cgi = itti_msg.cgi;
uc.get()->tai = itti_msg.tai;
if(itti_msg.rrc_cause != -1)
uc.get()->rrc_estb_cause = (e_Ngap_RRCEstablishmentCause)itti_msg.rrc_cause;
if(itti_msg.ueCtxReq == -1)
if (itti_msg.rrc_cause != -1)
uc.get()->rrc_estb_cause = (e_Ngap_RRCEstablishmentCause) itti_msg.rrc_cause;
if (itti_msg.ueCtxReq == -1)
uc.get()->isUeContextRequest = false;
else
uc.get()->isUeContextRequest = true;
uc.get()->ran_ue_ngap_id = itti_msg.ran_ue_ngap_id;
uc.get()->amf_ue_ngap_id = amf_ue_ngap_id;
std::string guti; bool is_guti_valid = false;
if(itti_msg.is_5g_s_tmsi_present){
std::string guti;
bool is_guti_valid = false;
if (itti_msg.is_5g_s_tmsi_present) {
guti = itti_msg.tai.mcc + itti_msg.tai.mnc + amf_cfg.guami.regionID + itti_msg._5g_s_tmsi;
is_guti_valid = true;
Logger::amf_app().debug("Receiving guti: %s", guti.c_str());
}
itti_uplink_nas_data_ind * itti_n1_msg = new itti_uplink_nas_data_ind(TASK_AMF_APP, TASK_AMF_N1);
itti_uplink_nas_data_ind *itti_n1_msg = new itti_uplink_nas_data_ind(TASK_AMF_APP, TASK_AMF_N1);
itti_n1_msg->amf_ue_ngap_id = amf_ue_ngap_id;
itti_n1_msg->ran_ue_ngap_id = itti_msg.ran_ue_ngap_id;
itti_n1_msg->is_nas_signalling_estab_req = true;
......@@ -243,28 +256,26 @@ void amf_app::handle_itti_message(itti_nas_signalling_establishment_request & it
itti_n1_msg->mcc = itti_msg.tai.mcc;
itti_n1_msg->mnc = itti_msg.tai.mnc;
itti_n1_msg->is_guti_valid = is_guti_valid;
if(is_guti_valid){
if (is_guti_valid) {
itti_n1_msg->guti = guti;
}
std::shared_ptr<itti_uplink_nas_data_ind> i = std::shared_ptr<itti_uplink_nas_data_ind>(itti_n1_msg);
std::shared_ptr<itti_uplink_nas_data_ind> i = std::shared_ptr < itti_uplink_nas_data_ind > (itti_n1_msg);
int ret = itti_inst->send_msg(i);
if (0 != ret) {
Logger::amf_app().error( "Could not send ITTI message %s to task TASK_AMF_N1", i->get_msg_name());
Logger::amf_app().error("Could not send ITTI message %s to task TASK_AMF_N1", i->get_msg_name());
}
}
}
/************************ SMF Client response handlers *****************************/
void amf_app::handle_post_sm_context_response_error_400(){
//SMF Client response handlers
//------------------------------------------------------------------------------
void amf_app::handle_post_sm_context_response_error_400() {
Logger::amf_app().error("post sm context response error 400");
}
bool amf_app::generate_5g_guti(uint32_t ranid, long amfid, string &mcc, string &mnc, uint32_t& tmsi){
string ue_context_key = "app_ue_ranid_"+to_string(ranid)+":amfid_"+to_string(amfid);
if(!is_ran_amf_id_2_ue_context(ue_context_key)){
bool amf_app::generate_5g_guti(uint32_t ranid, long amfid, string &mcc, string &mnc, uint32_t &tmsi) {
string ue_context_key = "app_ue_ranid_" + to_string(ranid) + ":amfid_" + to_string(amfid);
if (!is_ran_amf_id_2_ue_context(ue_context_key)) {
Logger::amf_app().error("no ue context for ran_amf_id(%s), exit", ue_context_key.c_str());
return false;
}
......@@ -273,6 +284,6 @@ bool amf_app::generate_5g_guti(uint32_t ranid, long amfid, string &mcc, string &
mcc = uc.get()->tai.mcc;
mnc = uc.get()->tai.mnc;
tmsi = golbal_tmsi;
golbal_tmsi ++;
golbal_tmsi++;
return true;
}
......@@ -45,53 +45,39 @@ using namespace std;
static uint32_t amf_app_ue_ngap_id_generator = 1;
namespace amf_application{
namespace amf_application {
#define TASK_AMF_APP_PERIODIC_STATISTICS (0)
class amf_app{
public:
class amf_app {
public:
explicit amf_app(const amf_config &amf_cfg);
amf_app(amf_app const&) = delete;
void operator=(amf_app const&) = delete;
void allRegistredModulesInit(const amf_modules & modules);
void allRegistredModulesInit(const amf_modules &modules);
long generate_amf_ue_ngap_id();
public://itti handlers
void handle_itti_message(itti_nas_signalling_establishment_request & itti_msg);
void handle_itti_message(itti_n1n2_message_transfer_request & itti_msg);
public://context management
//itti handlers
void handle_itti_message(itti_nas_signalling_establishment_request &itti_msg);
void handle_itti_message(itti_n1n2_message_transfer_request &itti_msg);
//context management
std::map<long, std::shared_ptr<ue_context>> amf_ue_ngap_id2ue_ctx;
mutable std::shared_mutex m_amf_ue_ngap_id2ue_ctx;
std::map<std::string, std::shared_ptr<ue_context>> ue_ctx_key;
mutable std::shared_mutex m_ue_ctx_key;
bool is_amf_ue_id_2_ue_context(const long & amf_ue_ngap_id) const;
std::shared_ptr<ue_context> amf_ue_id_2_ue_context(const long & amf_ue_ngap_id) const;
void set_amf_ue_ngap_id_2_ue_context(const long & amf_ue_ngap_id, std::shared_ptr<ue_context> uc);
bool is_amf_ue_id_2_ue_context(const long &amf_ue_ngap_id) const;
std::shared_ptr<ue_context> amf_ue_id_2_ue_context(const long &amf_ue_ngap_id) const;
void set_amf_ue_ngap_id_2_ue_context(const long &amf_ue_ngap_id, std::shared_ptr<ue_context> uc);
bool is_ran_amf_id_2_ue_context(const string & ue_context_key) const;
std::shared_ptr<ue_context> ran_amf_id_2_ue_context(const string & ue_context_key) const;
void set_ran_amf_id_2_ue_context(const string & ue_context_key, std::shared_ptr<ue_context> uc);
public:/*** SMF Client response handlers ****/
bool is_ran_amf_id_2_ue_context(const string &ue_context_key) const;
std::shared_ptr<ue_context> ran_amf_id_2_ue_context(const string &ue_context_key) const;
void set_ran_amf_id_2_ue_context(const string &ue_context_key, std::shared_ptr<ue_context> uc);
// SMF Client response handlers
void handle_post_sm_context_response_error_400();
public:
bool generate_5g_guti(uint32_t ranid, long amfid, string &mcc, string &mnc, uint32_t& tmsi);
//others
bool generate_5g_guti(uint32_t ranid, long amfid, string &mcc, string &mnc, uint32_t &tmsi);
};
}
#endif
......@@ -34,14 +34,14 @@
#include "amf_app.hpp"
#include "if.hpp"
#include "3gpp_ts24501.hpp"
extern "C"{
#include <arpa/inet.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include "common_defs.h"
extern "C" {
#include <arpa/inet.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include "common_defs.h"
}
#include <iostream>
......@@ -50,140 +50,147 @@ using namespace libconfig;
using namespace std;
using namespace amf_application;
namespace config{
namespace config {
amf_config::amf_config(){
}
amf_config::~amf_config(){}
int amf_config::load(const std::string &config_file){
cout<<endl;
Logger::amf_app().debug("Load amf system configuration file(%s)",config_file.c_str());
//------------------------------------------------------------------------------
amf_config::amf_config() {
}
//------------------------------------------------------------------------------
amf_config::~amf_config() {
}
//------------------------------------------------------------------------------
int amf_config::load(const std::string &config_file) {
cout << endl;
Logger::amf_app().debug("Load amf system configuration file(%s)", config_file.c_str());
Config cfg;
unsigned char buf_in6_addr[sizeof (struct in6_addr)];
try{
unsigned char buf_in6_addr[sizeof(struct in6_addr)];
try {
cfg.readFile(config_file.c_str());
}catch(const FileIOException &fioex){
} catch (const FileIOException &fioex) {
Logger::amf_app().error("I/O error while reading file %s - %s", config_file.c_str(), fioex.what());
throw;
}catch(const ParseException &pex){
} catch (const ParseException &pex) {
Logger::amf_app().error("Parse error at %s:%d - %s", pex.getFile(), pex.getLine(), pex.getError());
throw;
}
const Setting &root = cfg.getRoot();
try{
const Setting& amf_cfg = root[AMF_CONFIG_STRING_AMF_CONFIG];
}catch(const SettingNotFoundException &nfex){
try {
const Setting &amf_cfg = root[AMF_CONFIG_STRING_AMF_CONFIG];
} catch (const SettingNotFoundException &nfex) {
Logger::amf_app().error("%s : %s", nfex.what(), nfex.getPath());
return -1;
}
const Setting &amf_cfg = root[AMF_CONFIG_STRING_AMF_CONFIG];
try{
try {
amf_cfg.lookupValue(AMF_CONFIG_STRING_INSTANCE_ID, instance);
}catch(const SettingNotFoundException &nfex){
} catch (const SettingNotFoundException &nfex) {
Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath());
}
try{
try {
amf_cfg.lookupValue(AMF_CONFIG_STRING_STATISTICS_TIMER_INTERVAL, statistics_interval);
}catch(const SettingNotFoundException &nfex){
} catch (const SettingNotFoundException &nfex) {
Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath());
}
try{
try {
amf_cfg.lookupValue(AMF_CONFIG_STRING_PID_DIRECTORY, pid_dir);
}catch(const SettingNotFoundException &nfex){
} catch (const SettingNotFoundException &nfex) {
Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath());
}
try{
try {
amf_cfg.lookupValue(AMF_CONFIG_STRING_AMF_NAME, AMF_Name);
}catch(const SettingNotFoundException &nfex){
} catch (const SettingNotFoundException &nfex) {
Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath());
}
try{
try {
const Setting &guami_cfg = amf_cfg[AMF_CONFIG_STRING_GUAMI];
guami_cfg.lookupValue(AMF_CONFIG_STRING_MCC, guami.mcc);
guami_cfg.lookupValue(AMF_CONFIG_STRING_MNC, guami.mnc);
guami_cfg.lookupValue(AMF_CONFIG_STRING_RegionID, guami.regionID);
guami_cfg.lookupValue(AMF_CONFIG_STRING_AMFSetID, guami.AmfSetID);
guami_cfg.lookupValue(AMF_CONFIG_STRING_AMFPointer, guami.AmfPointer);
}catch(const SettingNotFoundException &nfex){
} catch (const SettingNotFoundException &nfex) {
Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath());
}
try{
try {
const Setting &guami_list_cfg = amf_cfg[AMF_CONFIG_STRING_ServedGUAMIList];
int count = guami_list_cfg.getLength();
for(int i=0;i<count;i++){
for (int i = 0; i < count; i++) {
guami_t guami;
const Setting &guami_item = guami_list_cfg[i];
guami_item.lookupValue(AMF_CONFIG_STRING_MCC,guami.mcc);
guami_item.lookupValue(AMF_CONFIG_STRING_MNC,guami.mnc);
guami_item.lookupValue(AMF_CONFIG_STRING_RegionID,guami.regionID);
guami_item.lookupValue(AMF_CONFIG_STRING_AMFSetID,guami.AmfSetID);
guami_item.lookupValue(AMF_CONFIG_STRING_AMFPointer,guami.AmfPointer);
guami_item.lookupValue(AMF_CONFIG_STRING_MCC, guami.mcc);
guami_item.lookupValue(AMF_CONFIG_STRING_MNC, guami.mnc);
guami_item.lookupValue(AMF_CONFIG_STRING_RegionID, guami.regionID);
guami_item.lookupValue(AMF_CONFIG_STRING_AMFSetID, guami.AmfSetID);
guami_item.lookupValue(AMF_CONFIG_STRING_AMFPointer, guami.AmfPointer);
guami_list.push_back(guami);
}
}catch(const SettingNotFoundException &nfex){
} catch (const SettingNotFoundException &nfex) {
Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath());
}
try{
try {
amf_cfg.lookupValue(AMF_CONFIG_STRING_RelativeAMFCapacity, relativeAMFCapacity);
}catch(const SettingNotFoundException &nfex){
} catch (const SettingNotFoundException &nfex) {
Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath());
}
try{
try {
const Setting &plmn_list_cfg = amf_cfg[AMF_CONFIG_STRING_PLMNSupportList];
int count = plmn_list_cfg.getLength();
for(int i=0;i<count;i++){
for (int i = 0; i < count; i++) {
plmn_item_t plmn_item;
const Setting & item = plmn_list_cfg[i];
const Setting &item = plmn_list_cfg[i];
item.lookupValue(AMF_CONFIG_STRING_MCC, plmn_item.mcc);
item.lookupValue(AMF_CONFIG_STRING_MNC, plmn_item.mnc);
item.lookupValue(AMF_CONFIG_STRING_TAC, plmn_item.tac);
const Setting &slice_list_cfg = plmn_list_cfg[i][AMF_CONFIG_STRING_SliceSupportList];
int numOfSlice = slice_list_cfg.getLength();
for(int j=0;j<numOfSlice;j++){
for (int j = 0; j < numOfSlice; j++) {
slice_t slice;
const Setting & slice_item = slice_list_cfg[j];
const Setting &slice_item = slice_list_cfg[j];
slice_item.lookupValue(AMF_CONFIG_STRING_SST, slice.sST);
slice_item.lookupValue(AMF_CONFIG_STRING_SD, slice.sD);
plmn_item.slice_list.push_back(slice);
}
plmn_list.push_back(plmn_item);
}
}catch(const SettingNotFoundException &nfex){
} catch (const SettingNotFoundException &nfex) {
Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath());
}
try{
try {
const Setting &new_if_cfg = amf_cfg[AMF_CONFIG_STRING_INTERFACES];
const Setting &n2_amf_cfg = new_if_cfg[AMF_CONFIG_STRING_INTERFACE_NGAP_AMF];
load_interface(n2_amf_cfg, n2);
const Setting &n11_cfg = new_if_cfg[AMF_CONFIG_STRING_INTERFACE_N11];
const Setting &smf_addr_pool = n11_cfg[AMF_CONFIG_STRING_SMF_INSTANCES_POOL];
int count = smf_addr_pool.getLength();
for(int i=0; i< count; i++){
const Setting & smf_addr_item = smf_addr_pool[i];
smf_inst_t smf_inst; string selected;
for (int i = 0; i < count; i++) {
const Setting &smf_addr_item = smf_addr_pool[i];
smf_inst_t smf_inst;
string selected;
smf_addr_item.lookupValue(AMF_CONFIG_STRING_SMF_INSTANCE_ID, smf_inst.id);
smf_addr_item.lookupValue(AMF_CONFIG_STRING_IPV4_ADDRESS, smf_inst.ipv4);
smf_addr_item.lookupValue(AMF_CONFIG_STRING_SMF_INSTANCE_PORT, smf_inst.port);
smf_addr_item.lookupValue(AMF_CONFIG_STRING_SMF_INSTANCE_VERSION, smf_inst.version);
smf_addr_item.lookupValue(AMF_CONFIG_STRING_SMF_INSTANCE_SELECTED, selected);
if(!selected.compare("true"))
if (!selected.compare("true"))
smf_inst.selected = true;
else
smf_inst.selected = false;
smf_pool.push_back(smf_inst);
}
}catch(const SettingNotFoundException &nfex){
} catch (const SettingNotFoundException &nfex) {
Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath());
return -1;
}
try{
try {
const Setting &core_config = amf_cfg[AMF_CONFIG_STRING_CORE_CONFIGURATION];
core_config.lookupValue(AMF_CONFIG_STRING_EMERGENCY_SUPPORT, is_emergency_support);
}catch(const SettingNotFoundException &nfex){
} catch (const SettingNotFoundException &nfex) {
Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath());
return -1;
}
try{
try {
const Setting &auth = amf_cfg[AMF_CONFIG_STRING_AUTHENTICATION];
auth.lookupValue(AMF_CONFIG_STRING_AUTH_MYSQL_SERVER, auth_para.mysql_server);
auth.lookupValue(AMF_CONFIG_STRING_AUTH_MYSQL_USER, auth_para.mysql_user);
......@@ -191,132 +198,136 @@ namespace config{
auth.lookupValue(AMF_CONFIG_STRING_AUTH_MYSQL_DB, auth_para.mysql_db);
auth.lookupValue(AMF_CONFIG_STRING_AUTH_OPERATOR_KEY, auth_para.operator_key);
auth.lookupValue(AMF_CONFIG_STRING_AUTH_RANDOM, auth_para.random);
}catch(const SettingNotFoundException &nfex){
} catch (const SettingNotFoundException &nfex) {
Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath());
return -1;
}
try{
try {
const Setting &nas = amf_cfg[AMF_CONFIG_STRING_NAS];
const Setting &intAlg = nas[AMF_CONFIG_STRING_NAS_SUPPORTED_INTEGRITY_ALGORITHM_LIST];
int intCount = intAlg.getLength();
for(int i=0; i<intCount; i++){
for (int i = 0; i < intCount; i++) {
string intAlgStr = intAlg[i];
if(!intAlgStr.compare("NIA0"))
if (!intAlgStr.compare("NIA0"))
nas_cfg.prefered_integrity_algorithm[i] = IA0_5G;
if(!intAlgStr.compare("NIA1"))
if (!intAlgStr.compare("NIA1"))
nas_cfg.prefered_integrity_algorithm[i] = IA1_128_5G;
if(!intAlgStr.compare("NIA2"))
if (!intAlgStr.compare("NIA2"))
nas_cfg.prefered_integrity_algorithm[i] = IA2_128_5G;
}
for(int i=intCount; i<8; i++){
for (int i = intCount; i < 8; i++) {
nas_cfg.prefered_integrity_algorithm[i] = IA0_5G;
}
const Setting &encAlg = nas[AMF_CONFIG_STRING_NAS_SUPPORTED_CIPHERING_ALGORITHM_LIST];
int encCount = encAlg.getLength();
for(int i=0; i<encCount; i++){
for (int i = 0; i < encCount; i++) {
string encAlgStr = encAlg[i];
if(!encAlgStr.compare("NEA0"))
if (!encAlgStr.compare("NEA0"))
nas_cfg.prefered_ciphering_algorithm[i] = EA0_5G;
if(!encAlgStr.compare("NEA1"))
if (!encAlgStr.compare("NEA1"))
nas_cfg.prefered_ciphering_algorithm[i] = EA1_128_5G;
if(!encAlgStr.compare("NEA2"))
if (!encAlgStr.compare("NEA2"))
nas_cfg.prefered_ciphering_algorithm[i] = EA2_128_5G;
}
for(int i=encCount; i<8; i++){
for (int i = encCount; i < 8; i++) {
nas_cfg.prefered_ciphering_algorithm[i] = EA0_5G;
}
}catch(const SettingNotFoundException &nfex){
} catch (const SettingNotFoundException &nfex) {
Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath());
return -1;
}
}
}
void amf_config::display(){
Logger::config().info( "======= BUPTv1.0 =======");
Logger::config().info( "Configuration AMF:");
Logger::config().info( "- Instance .......................: %d", instance);
Logger::config().info( "- PID dir ........................: %s", pid_dir.c_str());
Logger::config().info( "- AMF NAME........................: %s", AMF_Name.c_str());
Logger::config().info( "- GUAMI...........................: ");
Logger::config().info( " [%s] [%s] [%s] [%s] [%s]", guami.mcc.c_str(),guami.mnc.c_str(),guami.regionID.c_str(),guami.AmfSetID.c_str(),guami.AmfPointer.c_str());
Logger::config().info( "- ServedGUAMIList ................: ");
for(int i=0;i<guami_list.size();i++){
Logger::config().info( " [%s] [%s] [%s] [%s] [%s]", guami_list[i].mcc.c_str(),guami_list[i].mnc.c_str(),guami_list[i].regionID.c_str(),guami_list[i].AmfSetID.c_str(),guami_list[i].AmfPointer.c_str());
}
Logger::config().info( "- RelativeAMFCapacity ............: %d", relativeAMFCapacity);
Logger::config().info( "- PLMNSupportList ................: ");
for(int i=0;i<plmn_list.size();i++){
Logger::config().info( " [%s] [%s] ", plmn_list[i].mcc.c_str(),plmn_list[i].mnc.c_str());
Logger::config().info( " tac[%d]", plmn_list[i].tac);
Logger::config().info( " - SliceSupportList ............: ");
for(int j=0;j<plmn_list[i].slice_list.size();j++){
Logger::config().info( " [%s] [%s] ", plmn_list[i].slice_list[j].sST.c_str(),plmn_list[i].slice_list[j].sD.c_str());
}
}
Logger::config().info( "- Emergency Support ...............: %s", is_emergency_support.c_str());
Logger::config().info( "- MYSQL server ....................: %s", auth_para.mysql_server.c_str());
Logger::config().info( "- MYSQL user ......................: %s", auth_para.mysql_user.c_str());
Logger::config().info( "- MYSQL pass ......................: %s", auth_para.mysql_pass.c_str());
Logger::config().info( "- MYSQL db ........................: %s", auth_para.mysql_db.c_str());
Logger::config().info( "- operator key ....................: %s", auth_para.operator_key.c_str());
Logger::config().info( "- random ..........................: %s", auth_para.random.c_str());
Logger::config().info( "- Remote SMF Pool..................: ");
for(int i=0; i<smf_pool.size(); i++){
//------------------------------------------------------------------------------
void amf_config::display() {
Logger::config().info("======= AMF =======");
Logger::config().info("Configuration AMF:");
Logger::config().info("- Instance .......................: %d", instance);
Logger::config().info("- PID dir ........................: %s", pid_dir.c_str());
Logger::config().info("- AMF NAME........................: %s", AMF_Name.c_str());
Logger::config().info("- GUAMI...........................: ");
Logger::config().info(" [%s] [%s] [%s] [%s] [%s]", guami.mcc.c_str(), guami.mnc.c_str(), guami.regionID.c_str(), guami.AmfSetID.c_str(), guami.AmfPointer.c_str());
Logger::config().info("- ServedGUAMIList ................: ");
for (int i = 0; i < guami_list.size(); i++) {
Logger::config().info(" [%s] [%s] [%s] [%s] [%s]", guami_list[i].mcc.c_str(), guami_list[i].mnc.c_str(), guami_list[i].regionID.c_str(), guami_list[i].AmfSetID.c_str(), guami_list[i].AmfPointer.c_str());
}
Logger::config().info("- RelativeAMFCapacity ............: %d", relativeAMFCapacity);
Logger::config().info("- PLMNSupportList ................: ");
for (int i = 0; i < plmn_list.size(); i++) {
Logger::config().info(" [%s] [%s] ", plmn_list[i].mcc.c_str(), plmn_list[i].mnc.c_str());
Logger::config().info(" TAC[%d]", plmn_list[i].tac);
Logger::config().info(" - SliceSupportList ............: ");
for (int j = 0; j < plmn_list[i].slice_list.size(); j++) {
Logger::config().info(" [%s] [%s] ", plmn_list[i].slice_list[j].sST.c_str(), plmn_list[i].slice_list[j].sD.c_str());
}
}
Logger::config().info("- Emergency Support ...............: %s", is_emergency_support.c_str());
Logger::config().info("- MYSQL server ....................: %s", auth_para.mysql_server.c_str());
Logger::config().info("- MYSQL user ......................: %s", auth_para.mysql_user.c_str());
Logger::config().info("- MYSQL pass ......................: %s", auth_para.mysql_pass.c_str());
Logger::config().info("- MYSQL db ........................: %s", auth_para.mysql_db.c_str());
Logger::config().info("- operator key ....................: %s", auth_para.operator_key.c_str());
Logger::config().info("- random ..........................: %s", auth_para.random.c_str());
Logger::config().info("- Remote SMF Pool..................: ");
for (int i = 0; i < smf_pool.size(); i++) {
string selected;
if(smf_pool[i].selected) selected = "true";
else selected = "false";
Logger::config().info( " SMF_INSTANCE_ID(%d) : (%s:%s) version(%s) is selected(%s)", smf_pool[i].id, smf_pool[i].ipv4.c_str(), smf_pool[i].port.c_str(), smf_pool[i].version.c_str(), selected.c_str());
}
if (smf_pool[i].selected)
selected = "true";
else
selected = "false";
Logger::config().info(" SMF_INSTANCE_ID(%d) : (%s:%s) version(%s) is selected(%s)", smf_pool[i].id, smf_pool[i].ipv4.c_str(), smf_pool[i].port.c_str(), smf_pool[i].version.c_str(), selected.c_str());
}
}
int amf_config::load_interface(const libconfig::Setting& if_cfg, interface_cfg_t& cfg){
//------------------------------------------------------------------------------
int amf_config::load_interface(const libconfig::Setting &if_cfg, interface_cfg_t &cfg) {
if_cfg.lookupValue(AMF_CONFIG_STRING_INTERFACE_NAME, cfg.if_name);
util::trim(cfg.if_name);
if (not boost::iequals(cfg.if_name, "none")) {
std::string address = {};
std::string address = { };
if_cfg.lookupValue(AMF_CONFIG_STRING_IPV4_ADDRESS, address);
util::trim(address);
if (boost::iequals(address, "read")) {
if (get_inet_addr_infos_from_iface(cfg.if_name, cfg.addr4, cfg.network4, cfg.mtu)) {
Logger::amf_app().error("Could not read %s network interface configuration", cfg.if_name);
return RETURNerror;
return RETURNerror ;
}
} else {
std::vector<std::string> words;
std::vector < std::string > words;
boost::split(words, address, boost::is_any_of("/"), boost::token_compress_on);
if (words.size() != 2) {
Logger::amf_app().error("Bad value " AMF_CONFIG_STRING_IPV4_ADDRESS " = %s in config file", address.c_str());
return RETURNerror;
return RETURNerror ;
}
unsigned char buf_in_addr[sizeof(struct in6_addr)]; // you never know...
if (inet_pton (AF_INET, util::trim(words.at(0)).c_str(), buf_in_addr) == 1) {
memcpy (&cfg.addr4, buf_in_addr, sizeof (struct in_addr));
if (inet_pton(AF_INET, util::trim(words.at(0)).c_str(), buf_in_addr) == 1) {
memcpy(&cfg.addr4, buf_in_addr, sizeof(struct in_addr));
} else {
Logger::amf_app().error("In conversion: Bad value " AMF_CONFIG_STRING_IPV4_ADDRESS " = %s in config file", util::trim(words.at(0)).c_str());
return RETURNerror;
return RETURNerror ;
}
cfg.network4.s_addr = htons(ntohs(cfg.addr4.s_addr) & 0xFFFFFFFF << (32 - std::stoi (util::trim(words.at(1)))));
cfg.network4.s_addr = htons(ntohs(cfg.addr4.s_addr) & 0xFFFFFFFF << (32 - std::stoi(util::trim(words.at(1)))));
}
if_cfg.lookupValue(AMF_CONFIG_STRING_SCTP_PORT, cfg.port);
try {
const Setting& sched_params_cfg = if_cfg[AMF_CONFIG_STRING_SCHED_PARAMS];
const Setting &sched_params_cfg = if_cfg[AMF_CONFIG_STRING_SCHED_PARAMS];
load_thread_sched_params(sched_params_cfg, cfg.thread_rd_sched_params);
} catch(const SettingNotFoundException &nfex) {
} catch (const SettingNotFoundException &nfex) {
Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath());
}
}
return RETURNok;
}
return RETURNok ;
}
int amf_config::load_thread_sched_params(const Setting& thread_sched_params_cfg, util::thread_sched_params& cfg)
{
//------------------------------------------------------------------------------
int amf_config::load_thread_sched_params(const Setting &thread_sched_params_cfg, util::thread_sched_params &cfg) {
try {
thread_sched_params_cfg.lookupValue(AMF_CONFIG_STRING_THREAD_RD_CPU_ID, cfg.cpu_id);
} catch(const SettingNotFoundException &nfex) {
} catch (const SettingNotFoundException &nfex) {
Logger::amf_app().info("%s : %s, using defaults", nfex.what(), nfex.getPath());
}
try {
......@@ -335,9 +346,9 @@ int amf_config::load_thread_sched_params(const Setting& thread_sched_params_cfg,
cfg.sched_policy = SCHED_RR;
} else {
Logger::amf_app().error("thread_rd_sched_policy: %s, unknown in config file", thread_rd_sched_policy.c_str());
return RETURNerror;
return RETURNerror ;
}
} catch(const SettingNotFoundException &nfex) {
} catch (const SettingNotFoundException &nfex) {
Logger::amf_app().info("%s : %s, using defaults", nfex.what(), nfex.getPath());
}
......@@ -345,14 +356,12 @@ int amf_config::load_thread_sched_params(const Setting& thread_sched_params_cfg,
thread_sched_params_cfg.lookupValue(AMF_CONFIG_STRING_THREAD_RD_SCHED_PRIORITY, cfg.sched_priority);
if ((cfg.sched_priority > 99) || (cfg.sched_priority < 1)) {
Logger::amf_app().error("thread_rd_sched_priority: %d, must be in interval [1..99] in config file", cfg.sched_priority);
return RETURNerror;
return RETURNerror ;
}
} catch(const SettingNotFoundException &nfex) {
} catch (const SettingNotFoundException &nfex) {
Logger::amf_app().info("%s : %s, using defaults", nfex.what(), nfex.getPath());
}
return RETURNok;
return RETURNok ;
}
}
......@@ -95,20 +95,19 @@
#define AMF_CONFIG_STRING_NAS_SUPPORTED_INTEGRITY_ALGORITHM_LIST "ORDERED_SUPPORTED_INTEGRITY_ALGORITHM_LIST"
#define AMF_CONFIG_STRING_NAS_SUPPORTED_CIPHERING_ALGORITHM_LIST "ORDERED_SUPPORTED_CIPHERING_ALGORITHM_LIST"
using namespace libconfig;
using namespace std;
namespace config{
namespace config {
typedef struct{
typedef struct {
string mysql_server;
string mysql_user;
string mysql_pass;
string mysql_db;
string operator_key;
string random;
}auth_conf;
} auth_conf;
typedef struct interface_cfg_s {
std::string if_name;
......@@ -128,48 +127,48 @@ typedef struct itti_cfg_s {
util::thread_sched_params async_cmd_sched_params;
} itti_cfg_t;
typedef struct guami_s{
typedef struct guami_s {
string mcc;
string mnc;
string regionID;
string AmfSetID;
string AmfPointer;
}guami_t;
} guami_t;
typedef struct slice_s{
typedef struct slice_s {
string sST;
string sD;
}slice_t;
} slice_t;
typedef struct plmn_support_item_s{
typedef struct plmn_support_item_s {
string mcc;
string mnc;
uint32_t tac;
vector<slice_t> slice_list;
}plmn_item_t;
} plmn_item_t;
typedef struct{
typedef struct {
uint8_t prefered_integrity_algorithm[8];
uint8_t prefered_ciphering_algorithm[8];
}nas_conf_t;
} nas_conf_t;
typedef struct{
typedef struct {
int id;
string ipv4;
string port;
string version;
bool selected;
}smf_inst_t;
} smf_inst_t;
class amf_config{
public:
class amf_config {
public:
amf_config();
~amf_config();
int load(const std::string &config_file);
int load_interface(const Setting& if_cfg, interface_cfg_t & cfg);
int load_thread_sched_params(const libconfig::Setting& thread_sched_params_cfg, util::thread_sched_params& cfg);
int load_interface(const Setting &if_cfg, interface_cfg_t &cfg);
int load_thread_sched_params(const libconfig::Setting &thread_sched_params_cfg, util::thread_sched_params &cfg);
void display();
public:
public:
unsigned int instance;
string pid_dir;
interface_cfg_t n2;
......
......@@ -32,56 +32,57 @@
#include <string>
using namespace std;
namespace config {
namespace config{
int amf_modules::load(const std::string &config_file){
cout<<endl;
Logger::amf_app().debug("Load amf module configuration file(%s)",config_file.c_str());
//------------------------------------------------------------------------------
int amf_modules::load(const std::string &config_file) {
cout << endl;
Logger::amf_app().debug("Load amf module configuration file(%s)", config_file.c_str());
Config cfg;
try{
try {
cfg.readFile(config_file.c_str());
}catch(const FileIOException &fioex){
} catch (const FileIOException &fioex) {
Logger::amf_app().error("I/O error while reading file %s - %s", config_file.c_str(), fioex.what());
throw;
}catch(const ParseException &pex){
} catch (const ParseException &pex) {
Logger::amf_app().error("Parse error at %s:%d - %s", pex.getFile(), pex.getLine(), pex.getError());
throw;
}
const Setting &root = cfg.getRoot();
try{
const Setting& modules = root[MODULES_CONFIG_STRING_AMF_MODULES];
}catch(const SettingNotFoundException &nfex){
try {
const Setting &modules = root[MODULES_CONFIG_STRING_AMF_MODULES];
} catch (const SettingNotFoundException &nfex) {
Logger::amf_app().error("%s : %s", nfex.what(), nfex.getPath());
return -1;
}
const Setting &modules = root[MODULES_CONFIG_STRING_AMF_MODULES];
const Setting &msg = modules[MODULES_CONFIG_STRING_AMF_MODULES_NGAP_MESSAGE];
int count = msg.getLength();
for(int i=0; i< count; i++){
const Setting & item = msg[i];
for (int i = 0; i < count; i++) {
const Setting &item = msg[i];
std::string typeOfMessage;
int procedure_code;
item.lookupValue(MODULES_CONFIG_STRING_AMF_MODULES_NGAP_MESSAGE_NAME, msgName);
item.lookupValue(MODULES_CONFIG_STRING_AMF_MODULES_NGAP_MESSAGE_PROCEDURECODE, procedure_code);
item.lookupValue(MODULES_CONFIG_STRING_AMF_MODULES_NGAP_MESSAGE_TYPEOFMSG, typeOfMessage);
procedureCode = (Ngap_ProcedureCode_t)procedure_code;
if(!(typeOfMessage.compare("initialMessage"))){
procedureCode = (Ngap_ProcedureCode_t) procedure_code;
if (!(typeOfMessage.compare("initialMessage"))) {
typeOfMsg = Ngap_NGAP_PDU_PR_initiatingMessage;
}else if(!(typeOfMessage.compare("successfuloutcome"))){
} else if (!(typeOfMessage.compare("successfuloutcome"))) {
typeOfMsg = Ngap_NGAP_PDU_PR_successfulOutcome;
}else if(!(typeOfMessage.compare("unsuccessfuloutcome"))){
} else if (!(typeOfMessage.compare("unsuccessfuloutcome"))) {
typeOfMsg = Ngap_NGAP_PDU_PR_unsuccessfulOutcome;
}else{
} else {
Logger::config().error("wrong NGAP message configuration");
}
}
}
void amf_modules::display(){
Logger::config().info( "======= AMF Registered Modules =======");
Logger::config().info( "NGAP Message Modules:");
Logger::config().info( "- %s([%d,%d])\n", msgName.c_str(), procedureCode, typeOfMsg);
//------------------------------------------------------------------------------
void amf_modules::display() {
Logger::config().info("======= AMF Registered Modules =======");
Logger::config().info("NGAP Message Modules:");
Logger::config().info("- %s([%d,%d])\n", msgName.c_str(), procedureCode, typeOfMsg);
}
}
......@@ -44,25 +44,23 @@
#include "Ngap_ProcedureCode.h"
#include "Ngap_NGAP-PDU.h"
#define MODULES_CONFIG_STRING_AMF_MODULES "MODULES"
#define MODULES_CONFIG_STRING_AMF_MODULES_NGAP_MESSAGE "NGAP_MESSAGE"
#define MODULES_CONFIG_STRING_AMF_MODULES_NGAP_MESSAGE_NAME "MSG_NAME"
#define MODULES_CONFIG_STRING_AMF_MODULES_NGAP_MESSAGE_PROCEDURECODE "ProcedureCode"
#define MODULES_CONFIG_STRING_AMF_MODULES_NGAP_MESSAGE_TYPEOFMSG "TypeOfMessage"
using namespace libconfig;
namespace config{
namespace config {
class amf_modules{
public:
class amf_modules {
public:
int load(const std::string &config_file);
void display();
void makeModulesAlive();
private:
std::string msgName;//vector to store more msgs
private:
std::string msgName; //vector to store more msgs
Ngap_NGAP_PDU_PR typeOfMsg;
Ngap_ProcedureCode_t procedureCode;
// NGSetupRequestMsg *ngSetupRequest;
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -51,31 +51,31 @@
#include "mysql_db.hpp"
namespace amf_application{
namespace amf_application {
#define NAS_MESSAGE_DOWNLINK 1
#define NAS_MESSAGE_UPLINK 0
typedef enum{
typedef enum {
PlainNasMsg = 0x0,
IntegrityProtected = 0x1,
IntegrityProtectedAndCiphered = 0x2,
IntegrityProtectedWithNew5GNASSecurityContext = 0x3,
IntegrityProtectedAndCipheredWithNew5GNASSecurityContext = 0x4,
}SecurityHeaderType;
} SecurityHeaderType;
class amf_n1{
public:
class amf_n1 {
public:
amf_n1();
~amf_n1();
void handle_itti_message(itti_uplink_nas_data_ind&);
void handle_itti_message(itti_downlink_nas_transfer & itti_msg);
public: // nas message decode
void handle_itti_message(itti_downlink_nas_transfer &itti_msg);
public: // nas message decode
void nas_signalling_establishment_request_handle(SecurityHeaderType type, std::shared_ptr<nas_context> nc, uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, bstring plain_msg, std::string snn, uint8_t ulCount);
void uplink_nas_msg_handle(uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, bstring plain_msg);
bool check_security_header_type(SecurityHeaderType & type, uint8_t *buffer);
bool check_security_header_type(SecurityHeaderType &type, uint8_t *buffer);
public:
public:
std::map<long, std::shared_ptr<nas_context>> amfueid2nas_context; // amf ue ngap id
std::map<string, std::shared_ptr<nas_context>> imsi2nas_context;
std::map<std::string, long> supi2amfId;
......@@ -83,42 +83,42 @@ public:
std::map<std::string, std::shared_ptr<nas_context>> guti2nas_context;
mutable std::shared_mutex m_guti2nas_context;
bool is_guti_2_nas_context(const std::string & guti) const;
std::shared_ptr<nas_context> guti_2_nas_context(const std::string & guti) const;
void set_guti_2_nas_context(const std::string & guti, std::shared_ptr<nas_context>nc);
bool is_guti_2_nas_context(const std::string &guti) const;
std::shared_ptr<nas_context> guti_2_nas_context(const std::string &guti) const;
void set_guti_2_nas_context(const std::string &guti, std::shared_ptr<nas_context> nc);
mutable std::shared_mutex m_amfueid2nas_context;
bool is_amf_ue_id_2_nas_context(const long & amf_ue_ngap_id) const;
std::shared_ptr<nas_context> amf_ue_id_2_nas_context(const long & amf_ue_ngap_id) const;
void set_amf_ue_ngap_id_2_nas_context(const long & amf_ue_ngap_id, std::shared_ptr<nas_context> nc);
bool is_amf_ue_id_2_nas_context(const long &amf_ue_ngap_id) const;
std::shared_ptr<nas_context> amf_ue_id_2_nas_context(const long &amf_ue_ngap_id) const;
void set_amf_ue_ngap_id_2_nas_context(const long &amf_ue_ngap_id, std::shared_ptr<nas_context> nc);
database_t *db_desc;
private://nas message handlers
private: //nas message handlers
void ue_initiate_de_registration_handle(uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, bstring nas);
void registration_request_handle(bool isNasSig, std::shared_ptr<nas_context>nc, uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, std::string snn, bstring reg);
void registration_request_handle(bool isNasSig, std::shared_ptr<nas_context> nc, uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, std::string snn, bstring reg);
void authentication_response_handle(uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, bstring plain_msg);
void authentication_failure_handle(uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, bstring plain_msg);
void security_mode_complete_handle(uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, bstring nas_msg);
void security_mode_reject_handle(uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, bstring nas_msg);
void ul_nas_transport_handle(uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, bstring nas);
void sha256(unsigned char * message, int msg_len, unsigned char * output);
void sha256(unsigned char *message, int msg_len, unsigned char *output);
void service_request_handle(bool isNasSig, std::shared_ptr<nas_context> nc, uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, bstring nas);
private://authentication vector
private: //authentication vector
bool generate_authentication_vector();
private:
void itti_send_dl_nas_buffer_to_task_n2(bstring & b, uint32_t ran_ue_ngap_id, long amf_ue_ngap_id);
private://response message
private:
void itti_send_dl_nas_buffer_to_task_n2(bstring &b, uint32_t ran_ue_ngap_id, long amf_ue_ngap_id);
private: //response message
void response_registration_reject_msg(uint8_t cause_value, uint32_t ran_ue_ngap_id, long amf_ue_ngap_id);
public://procedures
void run_registration_procedure(std::shared_ptr<nas_context>&nc);
public: //procedures
void run_registration_procedure(std::shared_ptr<nas_context> &nc);
void run_initial_registration_procedure();
void run_mobility_registration_update_procedure(std::shared_ptr<nas_context>nc);
public://authentication
bool auth_vectors_generator(std::shared_ptr<nas_context>&nc);
bool authentication_vectors_generator_in_ausf(std::shared_ptr<nas_context>&nc);
bool authentication_vectors_generator_in_udm(std::shared_ptr<nas_context>&nc);
public://mysql handlers in mysql_db.cpp
void run_mobility_registration_update_procedure(std::shared_ptr<nas_context> nc);
public: //authentication
bool auth_vectors_generator(std::shared_ptr<nas_context> &nc);
bool authentication_vectors_generator_in_ausf(std::shared_ptr<nas_context> &nc);
bool authentication_vectors_generator_in_udm(std::shared_ptr<nas_context> &nc);
public: //mysql handlers in mysql_db.cpp
bool get_mysql_auth_info(std::string imsi, mysql_auth_info_t &resp);
void mysql_push_rand_sqn(std::string imsi, uint8_t *rand_p, uint8_t *sqn);
void mysql_increment_sqn(std::string imsi);
......@@ -130,29 +130,20 @@ public://mysql handlers in mysql_db.cpp
bool start_authentication_procedure(std::shared_ptr<nas_context> nc, int vindex, uint8_t ngksi);
bool check_nas_common_procedure_on_going(std::shared_ptr<nas_context> nc);
int security_select_algorithms(uint8_t nea, uint8_t nia, uint8_t &amf_nea, uint8_t &amf_nia);
bool start_security_mode_control_procedure(std::shared_ptr<nas_context>nc);
void encode_nas_message_protected(nas_secu_ctx * nsc, bool is_secu_ctx_new, uint8_t security_header_type, uint8_t direction, uint8_t *input_nas_buf, int input_nas_len, bstring & encrypted_nas);
bool start_security_mode_control_procedure(std::shared_ptr<nas_context> nc);
void encode_nas_message_protected(nas_secu_ctx *nsc, bool is_secu_ctx_new, uint8_t security_header_type, uint8_t direction, uint8_t *input_nas_buf, int input_nas_len, bstring &encrypted_nas);
bool nas_message_integrity_protected(nas_secu_ctx *nsc, uint8_t direction, uint8_t *input_nas, int input_nas_len, uint32_t &mac);
bool nas_message_cipher_protected(nas_secu_ctx *nsc, uint8_t direction, bstring input_nas, bstring &output_nas);
public:
public:
void dump_nas_message(uint8_t *buf, int len);
public:
public:
void ue_authentication_simulator(uint8_t *rand, uint8_t *autn);
void annex_a_4_33501(uint8_t ck[16], uint8_t ik[16], uint8_t *input, uint8_t rand[16], std::string serving_network, uint8_t *output);
public:
public:
void send_itti_to_smf_services_consumer(uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, uint8_t request_type, uint8_t pdu_session_id, bstring dnn, bstring sm_msg);
public:
public:
void update_ue_information_statics(ue_infos &ueItem, const string connStatus, const string registerStatus, uint32_t ranid, uint32_t amfid, string imsi, string guti, string mcc, string mnc, uint32_t cellId);
};
}
#endif
......@@ -35,7 +35,7 @@
#include <curl/curl.h>
#include <nlohmann/json.hpp>
/************* for smf_client ***************/
// For smf_client
#include "SmContextCreateData.h"
#include "SMContextsCollectionApi.h"
#include "ApiConfiguration.h"
......@@ -45,131 +45,138 @@
using namespace oai::smf::model;
using namespace oai::smf::api;
using namespace web; // Common features like URIs.
using namespace web::http; // Common HTTP functionality
using namespace web;
// Common features like URIs.
using namespace web::http;
// Common HTTP functionality
using namespace web::http::client;
using namespace config;
using namespace amf_application;
extern itti_mw * itti_inst;
extern itti_mw *itti_inst;
extern amf_config amf_cfg;
extern amf_n11 * amf_n11_inst;
extern amf_n11 *amf_n11_inst;
extern amf_n1 * amf_n1_inst;
extern amf_n1 *amf_n1_inst;
extern void msg_str_2_msg_hex(std::string msg, bstring &b);
extern void convert_string_2_hex(std::string&input, std::string&output);
extern void convert_string_2_hex(std::string &input, std::string &output);
extern void print_buffer(const std::string app, const std::string commit, uint8_t *buf, int len);
extern bool multipart_parser(string input, string &jsonData, string &n1sm, string &n2sm);
extern unsigned char * format_string_as_hex(std::string str);
extern unsigned char* format_string_as_hex(std::string str);
extern char* bstring2charString(bstring b);
std::size_t callback(
const char* in,
std::size_t size,
std::size_t num,
std::string* out)
{
std::size_t callback(const char *in, std::size_t size, std::size_t num, std::string *out) {
const std::size_t totalBytes(size * num);
out->append(in, totalBytes);
return totalBytes;
}
void octet_stream_2_hex_stream(uint8_t *buf, int len, string &out){
void octet_stream_2_hex_stream(uint8_t *buf, int len, string &out) {
out = "";
char *tmp = (char*)calloc(1, 2*len*sizeof(uint8_t)+1);
for(int i=0; i<len; i++){
sprintf(tmp+2*i, "%02x", buf[i]);
char *tmp = (char*) calloc(1, 2 * len * sizeof(uint8_t) + 1);
for (int i = 0; i < len; i++) {
sprintf(tmp + 2 * i, "%02x", buf[i]);
}
tmp[2*len] = '\0';
tmp[2 * len] = '\0';
out = tmp;
printf("n1sm buffer: %s\n", out.c_str());
}
/****************************************************/
/** used to run NF(s) consumer, like smf_client ****/
/***************************************************/
void amf_n11_task(void*);
void amf_n11_task(void*){
void amf_n11_task(void*) {
const task_id_t task_id = TASK_AMF_N11;
itti_inst->notify_task_ready(task_id);
do{
do {
std::shared_ptr<itti_msg> shared_msg = itti_inst->receive_msg(task_id);
auto *msg = shared_msg.get();
switch(msg->msg_type){
case SMF_SERVICES_CONSUMER:{
Logger::task_amf_n11().info("running SMF_SERVICES_CONSUMER");
switch (msg->msg_type) {
case SMF_SERVICES_CONSUMER: {
Logger::task_amf_n11().info("Running SMF_SERVICES_CONSUMER");
itti_smf_services_consumer *m = dynamic_cast<itti_smf_services_consumer*>(msg);
amf_n11_inst->handle_itti_message(ref(*m));
}break;
case NSMF_PDU_SESS_UPDATE_SMCTX:{
Logger::task_amf_n11().info("receive NSMF_PDU_SESS_UPDATE_SMCTX, handling ...");
}
break;
case NSMF_PDU_SESS_UPDATE_SMCTX: {
Logger::task_amf_n11().info("Receive NSMF_PDU_SESS_UPDATE_SMCTX, handling ...");
itti_nsmf_pdusession_update_sm_context *m = dynamic_cast<itti_nsmf_pdusession_update_sm_context*>(msg);
amf_n11_inst->handle_itti_message(ref(*m));
}break;
case PDU_SESS_RES_SET_RESP:{
Logger::task_amf_n11().info("receive PDU_SESS_RES_SET_RESP, handling ...");
}
break;
case PDU_SESS_RES_SET_RESP: {
Logger::task_amf_n11().info("Receive PDU_SESS_RES_SET_RESP, handling ...");
itti_pdu_session_resource_setup_response *m = dynamic_cast<itti_pdu_session_resource_setup_response*>(msg);
amf_n11_inst->handle_itti_message(ref(*m));
}break;
}
}while(true);
break;
}
} while (true);
}
amf_n11::amf_n11(){
if(itti_inst->create_task(TASK_AMF_N11, amf_n11_task, nullptr) ) {
Logger::amf_n11().error( "Cannot create task TASK_AMF_N1" );
throw std::runtime_error( "Cannot create task TASK_AMF_N1" );
//------------------------------------------------------------------------------
amf_n11::amf_n11() {
if (itti_inst->create_task(TASK_AMF_N11, amf_n11_task, nullptr)) {
Logger::amf_n11().error("Cannot create task TASK_AMF_N1");
throw std::runtime_error("Cannot create task TASK_AMF_N1");
}
Logger::task_amf_n11().startup( "Started" );
Logger::task_amf_n11().debug("construct amf_n1 successfully");
Logger::task_amf_n11().startup("Started");
Logger::task_amf_n11().debug("Construct amf_n1 successfully");
}
amf_n11::~amf_n11(){}
//------------------------------------------------------------------------------
amf_n11::~amf_n11() {
}
// itti message handlers
//------------------------------------------------------------------------------
void amf_n11::handle_itti_message(itti_pdu_session_resource_setup_response &itti_msg) {
}
/***************************** itti message handlers *********************************/
void amf_n11::handle_itti_message(itti_pdu_session_resource_setup_response &itti_msg){}
void amf_n11::handle_itti_message(itti_nsmf_pdusession_update_sm_context &itti_msg){
//------------------------------------------------------------------------------
void amf_n11::handle_itti_message(itti_nsmf_pdusession_update_sm_context &itti_msg) {
string supi = pduid2supi.at(itti_msg.pdu_session_id);
Logger::amf_n11().debug("Try to find supi(%s) from pdusession_id(%d)", supi.c_str(), itti_msg.pdu_session_id);
std::shared_ptr<pdu_session_context> psc;
if(is_supi_to_pdu_ctx(supi)){
if (is_supi_to_pdu_ctx(supi)) {
psc = supi_to_pdu_ctx(supi);
}else{
Logger::amf_n11().error("trying to find psu_session_context with supi(%s), Falied", supi.c_str());
} else {
Logger::amf_n11().error("Trying to find psu_session_context with supi(%s), Falied", supi.c_str());
return;
}
string smf_addr;
if(!psc.get()->smf_avaliable){
if(!smf_selection_from_configuration(smf_addr)){
Logger::amf_n11().error("No candidate smf is avaliable");
if (!psc.get()->smf_avaliable) {
if (!smf_selection_from_configuration(smf_addr)) {
Logger::amf_n11().error("No candidate SMF is available");
return;
}
}else{
} else {
smf_selection_from_context(smf_addr);
}
string remote_uri = smf_addr + "/nsmf-pdusession/v2/sm-contexts/" + "1" + "/modify";//scid
string remote_uri = smf_addr + "/nsmf-pdusession/v2/sm-contexts/" + "1" + "/modify"; //scid
nlohmann::json pdu_session_update_request;
pdu_session_update_request["n2SmInfoType"] = "PDU_RES_SETUP_RSP";
pdu_session_update_request["n2SmInfo"]["contentId"] = "n2SmMsg";
std::string json_part = pdu_session_update_request.dump();
std::string n2SmMsg;
octet_stream_2_hex_stream((uint8_t*)bdata(itti_msg.n2sm), blength(itti_msg.n2sm), n2SmMsg);
curl_http_client(remote_uri ,json_part, "", n2SmMsg, supi, itti_msg.pdu_session_id);
octet_stream_2_hex_stream((uint8_t*) bdata(itti_msg.n2sm), blength(itti_msg.n2sm), n2SmMsg);
curl_http_client(remote_uri, json_part, "", n2SmMsg, supi, itti_msg.pdu_session_id);
}
void amf_n11::handle_itti_message(itti_smf_services_consumer& smf){
//------------------------------------------------------------------------------
void amf_n11::handle_itti_message(itti_smf_services_consumer &smf) {
std::shared_ptr<nas_context> nc;
nc = amf_n1_inst->amf_ue_id_2_nas_context(smf.amf_ue_ngap_id);
string supi = "imsi-" + nc.get()->imsi;
std::shared_ptr<pdu_session_context> psc;
if(is_supi_to_pdu_ctx(supi)){
if (is_supi_to_pdu_ctx(supi)) {
psc = supi_to_pdu_ctx(supi);
}else{
psc = std::shared_ptr<pdu_session_context>(new pdu_session_context());
} else {
psc = std::shared_ptr < pdu_session_context > (new pdu_session_context());
set_supi_to_pdu_ctx(supi, psc);
}
......@@ -181,38 +188,42 @@ void amf_n11::handle_itti_message(itti_smf_services_consumer& smf){
psc.get()->pdu_session_id = smf.pdu_sess_id;
//parse binary dnn and store
std::string dnn = "default";
if ((smf.dnn != nullptr) && (blength(smf.dnn) > 0)){
char * tmp = bstring2charString(smf.dnn);
if ((smf.dnn != nullptr) && (blength(smf.dnn) > 0)) {
char *tmp = bstring2charString(smf.dnn);
dnn = tmp;
free (tmp);
free(tmp);
tmp = nullptr;
}
Logger::amf_n11().debug("requested DNN: %s", dnn.c_str());
Logger::amf_n11().debug("Requested DNN: %s", dnn.c_str());
psc.get()->dnn = dnn;
string smf_addr;
if(!psc.get()->smf_avaliable){
if(!smf_selection_from_configuration(smf_addr)){
Logger::amf_n11().error("No candidate smf is avaliable");
if (!psc.get()->smf_avaliable) {
if (!smf_selection_from_configuration(smf_addr)) {
Logger::amf_n11().error("No candidate for SMF is available");
return;
}
}else{
} else {
smf_selection_from_context(smf_addr);
}
switch(smf.req_type & 0x07){
case PDU_SESSION_INITIAL_REQUEST:{
switch (smf.req_type & 0x07) {
case PDU_SESSION_INITIAL_REQUEST: {
handle_pdu_session_initial_request(supi, psc, smf_addr, smf.sm_msg, dnn);
}break;
case EXISTING_PDU_SESSION:{
}break;
case PDU_SESSION_MODIFICATION_REQUEST:{
}break;
}
break;
case EXISTING_PDU_SESSION: {
}
break;
case PDU_SESSION_MODIFICATION_REQUEST: {
}
break;
}
}
void amf_n11::handle_pdu_session_initial_request(string supi, std::shared_ptr<pdu_session_context> psc, string smf_addr, bstring sm_msg, string dnn){
//------------------------------------------------------------------------------
void amf_n11::handle_pdu_session_initial_request(string supi, std::shared_ptr<pdu_session_context> psc, string smf_addr, bstring sm_msg, string dnn) {
string remote_uri = smf_addr + "/nsmf-pdusession/v2/sm-contexts";
nlohmann::json pdu_session_establishment_request;
pdu_session_establishment_request["supi"] = supi.c_str();
......@@ -234,60 +245,69 @@ void amf_n11::handle_pdu_session_initial_request(string supi, std::shared_ptr<pd
std::string json_part = pdu_session_establishment_request.dump();
std::string n1SmMsg;
octet_stream_2_hex_stream((uint8_t*)bdata(sm_msg), blength(sm_msg), n1SmMsg);
curl_http_client(remote_uri ,json_part, n1SmMsg, "", supi, psc.get()->pdu_session_id);
octet_stream_2_hex_stream((uint8_t*) bdata(sm_msg), blength(sm_msg), n1SmMsg);
curl_http_client(remote_uri, json_part, n1SmMsg, "", supi, psc.get()->pdu_session_id);
}
/************************************************* context management functions *********************************/
//Context management functions
//------------------------------------------------------------------------------
bool amf_n11::is_supi_to_pdu_ctx(const string &supi) const {
std::shared_lock lock(m_supi2pdu);
return bool{supi2pdu.count(supi) > 0};
return bool { supi2pdu.count(supi) > 0 };
}
std::shared_ptr<pdu_session_context> amf_n11::supi_to_pdu_ctx(const string & supi) const {
std::shared_ptr<pdu_session_context> amf_n11::supi_to_pdu_ctx(const string &supi) const {
std::shared_lock lock(m_supi2pdu);
return supi2pdu.at(supi);
}
void amf_n11::set_supi_to_pdu_ctx(const string &supi, std::shared_ptr<pdu_session_context> psc){
//------------------------------------------------------------------------------
void amf_n11::set_supi_to_pdu_ctx(const string &supi, std::shared_ptr<pdu_session_context> psc) {
std::shared_lock lock(m_supi2pdu);
supi2pdu[supi] = psc;
}
/************************************** smf selection ********************************/
bool amf_n11::smf_selection_from_configuration(string & smf_addr){
for(int i=0; i<amf_cfg.smf_pool.size(); i++){
if(amf_cfg.smf_pool[i].selected){
smf_addr = "http://"+amf_cfg.smf_pool[i].ipv4+":"+amf_cfg.smf_pool[i].port;
//SMF selection
//------------------------------------------------------------------------------
bool amf_n11::smf_selection_from_configuration(string &smf_addr) {
for (int i = 0; i < amf_cfg.smf_pool.size(); i++) {
if (amf_cfg.smf_pool[i].selected) {
smf_addr = "http://" + amf_cfg.smf_pool[i].ipv4 + ":" + amf_cfg.smf_pool[i].port;
return true;
}
}
return false;
}
bool amf_n11::smf_selection_from_context(string & smf_addr){
//------------------------------------------------------------------------------
bool amf_n11::smf_selection_from_context(string &smf_addr) {
}
/************************************* handlers for smf client response **************************/
void amf_n11::handle_post_sm_context_response_error_400(){}
void amf_n11::handle_post_sm_context_response_error(long code, string cause, bstring n1sm, string supi, uint8_t pdu_session_id){
print_buffer("amf_n11", "n1 sm", (uint8_t*)bdata(n1sm), blength(n1sm));
// handlers for smf client response
//------------------------------------------------------------------------------
void amf_n11::handle_post_sm_context_response_error_400() {
}
//------------------------------------------------------------------------------
void amf_n11::handle_post_sm_context_response_error(long code, string cause, bstring n1sm, string supi, uint8_t pdu_session_id) {
print_buffer("amf_n11", "n1 sm", (uint8_t*) bdata(n1sm), blength(n1sm));
itti_n1n2_message_transfer_request *itti_msg = new itti_n1n2_message_transfer_request(TASK_AMF_N11, TASK_AMF_APP);
itti_msg->n1sm = n1sm;
itti_msg->is_n2sm_set = false;
itti_msg->supi = supi;
itti_msg->pdu_session_id = pdu_session_id;
std::shared_ptr<itti_n1n2_message_transfer_request> i = std::shared_ptr<itti_n1n2_message_transfer_request>(itti_msg);
std::shared_ptr<itti_n1n2_message_transfer_request> i = std::shared_ptr < itti_n1n2_message_transfer_request > (itti_msg);
int ret = itti_inst->send_msg(i);
if (0 != ret) {
Logger::amf_n1().error( "Could not send ITTI message %s to task TASK_AMF_APP", i->get_msg_name());
Logger::amf_n1().error("Could not send ITTI message %s to task TASK_AMF_APP", i->get_msg_name());
}
}
void amf_n11::curl_http_client(string remoteUri, string jsonData, string n1SmMsg, string n2SmMsg, string supi, uint8_t pdu_session_id){
Logger::amf_n11().debug("call smf service operation: %s", remoteUri.c_str());
//------------------------------------------------------------------------------
void amf_n11::curl_http_client(string remoteUri, string jsonData, string n1SmMsg, string n2SmMsg, string supi, uint8_t pdu_session_id) {
Logger::amf_n11().debug("Call SMF service operation: %s", remoteUri.c_str());
CURL *curl = curl_easy_init();
if(curl){
if (curl) {
CURLcode res;
struct curl_slist *headers = nullptr;
struct curl_slist *slist = nullptr;
......@@ -299,7 +319,7 @@ void amf_n11::curl_http_client(string remoteUri, string jsonData, string n1SmMsg
headers = curl_slist_append(headers, "content-type: multipart/related");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_URL, remoteUri.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPGET,1);
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 100L);
mime = curl_mime_init(curl);
......@@ -310,20 +330,18 @@ void amf_n11::curl_http_client(string remoteUri, string jsonData, string n1SmMsg
curl_mime_data(part, jsonData.c_str(), CURL_ZERO_TERMINATED);
curl_mime_type(part, "application/json");
if(n1SmMsg != ""){
Logger::amf_n11().debug("is there ok? n1");
if (n1SmMsg != "") {
unsigned char *n1_msg_hex = format_string_as_hex(n1SmMsg);
part = curl_mime_addpart(mime);
curl_mime_data(part, reinterpret_cast<const char*>(n1_msg_hex), n1SmMsg.length()/2);
curl_mime_data(part, reinterpret_cast<const char*>(n1_msg_hex), n1SmMsg.length() / 2);
curl_mime_type(part, "application/vnd.3gpp.5gnas");
//curl_mime_name (part, "n1SmMsg");
}
if(n2SmMsg != ""){
if (n2SmMsg != "") {
unsigned char *n2_msg_hex = format_string_as_hex(n2SmMsg);
part = curl_mime_addpart(mime);
curl_mime_data(part, reinterpret_cast<const char*>(n2_msg_hex), n2SmMsg.length()/2);
curl_mime_data(part, reinterpret_cast<const char*>(n2_msg_hex), n2SmMsg.length() / 2);
curl_mime_type(part, "application/vnd.3gpp.ngap");
//curl_mime_name (part, "n2SmMsg");
}
......@@ -333,7 +351,7 @@ void amf_n11::curl_http_client(string remoteUri, string jsonData, string n1SmMsg
// Response information.
long httpCode(0);
std::unique_ptr<std::string> httpData(new std::string());
std::unique_ptr < std::string > httpData(new std::string());
// Hook up data handling function.
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &callback);
......@@ -349,29 +367,30 @@ void amf_n11::curl_http_client(string remoteUri, string jsonData, string n1SmMsg
string n2sm = "";
bool is_response_ok = true;
Logger::amf_n11().debug("Get response with httpcode (%d)", httpCode);
if(httpCode == 0){
if (httpCode == 0) {
Logger::amf_n11().error("Cannot get response When calling %s", remoteUri.c_str());
return;
}
if(httpCode != 200 && httpCode != 201){
if (httpCode != 200 && httpCode != 201) {
is_response_ok = false;
if(!(multipart_parser(response, jsonData, n1sm, n2sm))){
if (!(multipart_parser(response, jsonData, n1sm, n2sm))) {
Logger::amf_n11().error("Could not get the cause from the response");
}
}
nlohmann::json response_data;
bstring n1sm_hex;
if(!is_response_ok){
if (!is_response_ok) {
response_data = nlohmann::json::parse(jsonData);
Logger::amf_n11().debug("Get response with jsonData: %s", jsonData.c_str());
msg_str_2_msg_hex(n1sm.substr(0, n1sm.length()-2), n1sm_hex);//pdu session establishment reject bugs from SMF
print_buffer("amf_n11", "Get response with n1sm:", (uint8_t*)bdata(n1sm_hex), blength(n1sm_hex));
msg_str_2_msg_hex(n1sm.substr(0, n1sm.length() - 2), n1sm_hex); //pdu session establishment reject bugs from SMF
print_buffer("amf_n11", "Get response with n1sm:", (uint8_t*) bdata(n1sm_hex), blength(n1sm_hex));
string cause = response_data["error"]["cause"];
Logger::amf_n11().error("call Network Function services failure ");
Logger::amf_n11().error("Call Network Function services failure ");
Logger::amf_n11().info("Cause value: %s", cause.c_str());
if(!cause.compare("DNN_DENIED")) handle_post_sm_context_response_error(httpCode, cause, n1sm_hex, supi, pdu_session_id);
if (!cause.compare("DNN_DENIED"))
handle_post_sm_context_response_error(httpCode, cause, n1sm_hex, supi, pdu_session_id);
}
curl_slist_free_all(headers);
......
......@@ -35,68 +35,32 @@
#include <string>
using namespace std;
namespace amf_application{
namespace amf_application {
class amf_n11{
public:
class amf_n11 {
public:
amf_n11();
~amf_n11();
public:
void handle_itti_message(itti_smf_services_consumer &);
void handle_itti_message(itti_smf_services_consumer&);
void handle_pdu_session_initial_request(string supi, std::shared_ptr<pdu_session_context> psc, string smf_addr, bstring sm_msg, string dnn);
void handle_itti_message(itti_pdu_session_resource_setup_response &itti_msg);
void handle_itti_message(itti_nsmf_pdusession_update_sm_context &itti_msg);
public:
std::map<string, std::shared_ptr<pdu_session_context>> supi2pdu; // amf ue ngap id
mutable std::shared_mutex m_supi2pdu;
bool is_supi_to_pdu_ctx(const string &supi) const;
std::shared_ptr<pdu_session_context> supi_to_pdu_ctx(const string & supi) const;
std::shared_ptr<pdu_session_context> supi_to_pdu_ctx(const string &supi) const;
void set_supi_to_pdu_ctx(const string &supi, std::shared_ptr<pdu_session_context> psc);
public:
std::map<uint8_t, string> pduid2supi;
public:
bool smf_selection_from_configuration(string & smf_addr);
bool smf_selection_from_context(string & smf_addr);
public:
bool smf_selection_from_configuration(string &smf_addr);
bool smf_selection_from_context(string &smf_addr);
void handle_post_sm_context_response_error_400();
void handle_post_sm_context_response_error(long code, string cause, bstring n1sm, string supi, uint8_t pdu_session_id);
public:
void curl_http_client(string remoteUri, string jsonData, string n1SmMsg, string n2SmMsg, string supi, uint8_t pdu_session_id);
};
}
#endif
......@@ -41,9 +41,7 @@
#include "InitialContextSetupRequest.hpp"
#include "PduSessionResourceSetupRequest.hpp"
#include "UEContextReleaseCommand.hpp"
#include "amf_statistics.hpp"
#include "Ngap_Cause.h"
#include "Ngap_CauseRadioNetwork.h"
#include "Ngap_TimeToWait.h"
......@@ -51,133 +49,153 @@
using namespace amf_application;
using namespace std;
using namespace config;
extern itti_mw * itti_inst;
extern amf_n2 * amf_n2_inst;
extern amf_n1 * amf_n1_inst;
extern itti_mw *itti_inst;
extern amf_n2 *amf_n2_inst;
extern amf_n1 *amf_n1_inst;
extern amf_config amf_cfg;
extern amf_app *amf_app_inst;
extern statistics stacs;
void amf_n2_task(void*);
void amf_n2_task(void *args_p){
void amf_n2_task(void*);
//------------------------------------------------------------------------------
void amf_n2_task(void *args_p) {
const task_id_t task_id = TASK_AMF_N2;
itti_inst->notify_task_ready(task_id);
do{
do {
std::shared_ptr<itti_msg> shared_msg = itti_inst->receive_msg(task_id);
auto *msg = shared_msg.get();
switch(msg->msg_type){
case NEW_SCTP_ASSOCIATION:{
switch (msg->msg_type) {
case NEW_SCTP_ASSOCIATION: {
Logger::task_amf_n2().info("Received NEW_SCTP_ASSOCIATION");
itti_new_sctp_association *m = dynamic_cast<itti_new_sctp_association*>(msg);
amf_n2_inst->handle_itti_message(ref(*m));
}break;
case NG_SETUP_REQ:{
}
break;
case NG_SETUP_REQ: {
Logger::task_amf_n2().info("Received NGSetupRequest message, handling");
itti_ng_setup_request *m = dynamic_cast<itti_ng_setup_request*>(msg);
amf_n2_inst->handle_itti_message(ref(*m));
}break;
case INITIAL_UE_MSG:{
}
break;
case INITIAL_UE_MSG: {
Logger::task_amf_n2().info("Received INITIAL_UE_MESSAGE message, handling");
itti_initial_ue_message *m = dynamic_cast<itti_initial_ue_message*>(msg);
amf_n2_inst->handle_itti_message(ref(*m));
}break;
case ITTI_UL_NAS_TRANSPORT:{
}
break;
case ITTI_UL_NAS_TRANSPORT: {
Logger::task_amf_n2().info("Received UPLINK_NAS_TRANSPORT message, handling");
itti_ul_nas_transport *m = dynamic_cast<itti_ul_nas_transport*>(msg);
amf_n2_inst->handle_itti_message(ref(*m));
}break;
case ITTI_DL_NAS_TRANSPORT:{
}
break;
case ITTI_DL_NAS_TRANSPORT: {
Logger::task_amf_n2().info("Encoding DOWNLINK NAS TRANSPORT message, sending ");
itti_dl_nas_transport *m = dynamic_cast<itti_dl_nas_transport*>(msg);
amf_n2_inst->handle_itti_message(ref(*m));
}break;
case PDU_SESSION_RESOURCE_SETUP_REQUEST:{
}
break;
case PDU_SESSION_RESOURCE_SETUP_REQUEST: {
Logger::task_amf_n2().info("Encoding PDU SESSION RESOURCE SETUP REQUEST message, sending ");
itti_pdu_session_resource_setup_request *m = dynamic_cast<itti_pdu_session_resource_setup_request*>(msg);
amf_n2_inst->handle_itti_message(ref(*m));
}break;
case INITIAL_CONTEXT_SETUP_REQUEST:{
}
break;
case INITIAL_CONTEXT_SETUP_REQUEST: {
Logger::task_amf_n2().info("Encoding INITIAL CONTEXT SETUP REQUEST message, sending ");
itti_initial_context_setup_request *m = dynamic_cast<itti_initial_context_setup_request*>(msg);
amf_n2_inst->handle_itti_message(ref(*m));
}break;
case UE_CONTEXT_RELEASE_REQUEST:{
}
break;
case UE_CONTEXT_RELEASE_REQUEST: {
Logger::task_amf_n2().info("Received UE_CONTEXT_RELEASE_REQUEST message, handling");
itti_ue_context_release_request *m = dynamic_cast<itti_ue_context_release_request*>(msg);
amf_n2_inst->handle_itti_message(ref(*m));
}break;
case UE_RADIO_CAP_IND:{
}
break;
case UE_RADIO_CAP_IND: {
Logger::task_amf_n2().info("Received UE_RADIO_CAP_IND message, handling");
itti_ue_radio_capability_indication *m = dynamic_cast<itti_ue_radio_capability_indication*>(msg);
amf_n2_inst->handle_itti_message(ref(*m));
}break;
default:
Logger::task_amf_n2().info( "no handler for msg type %d", msg->msg_type);
}
}while(true);
break;
default:
Logger::task_amf_n2().info("No handler for msg type %d", msg->msg_type);
}
} while (true);
}
amf_n2::amf_n2(const string &address, const uint16_t port_num) : ngap_app(address, port_num){
if (itti_inst->create_task(TASK_AMF_N2, amf_n2_task, nullptr) ) {
Logger::amf_n2().error( "Cannot create task TASK_AMF_N2" );
throw std::runtime_error( "Cannot create task TASK_AMF_N2" );
//------------------------------------------------------------------------------
amf_n2::amf_n2(const string &address, const uint16_t port_num)
:
ngap_app(address, port_num) {
if (itti_inst->create_task(TASK_AMF_N2, amf_n2_task, nullptr)) {
Logger::amf_n2().error("Cannot create task TASK_AMF_N2");
throw std::runtime_error("Cannot create task TASK_AMF_N2");
}
Logger::task_amf_n2().startup( "Started" );
Logger::task_amf_n2().startup("Started");
Logger::task_amf_n2().debug("construct amf_n2 successfully");
}
amf_n2::~amf_n2(){}
}
//------------------------------------------------------------------------------
amf_n2::~amf_n2() {
}
//NGAP Messages Handlers
//------------------------------------------------------------------------------
/******************************************************** NGAP Messages Handlers******************************************************************/
void amf_n2::handle_itti_message(itti_new_sctp_association &new_assoc) {
} //handled in class ngap_app
void amf_n2::handle_itti_message(itti_new_sctp_association &new_assoc){}//handled in class ngap_app
/************************* NG_SETUP_REQUEST Handler **************************/
void amf_n2::handle_itti_message(itti_ng_setup_request & itti_msg){
Logger::amf_n2().debug("parameters(assoc_id(%d))(stream(%d))",itti_msg.assoc_id, itti_msg.stream);
// NG_SETUP_REQUEST Handler
//------------------------------------------------------------------------------
void amf_n2::handle_itti_message(itti_ng_setup_request &itti_msg) {
Logger::amf_n2().debug("parameters(assoc_id(%d))(stream(%d))", itti_msg.assoc_id, itti_msg.stream);
std::shared_ptr<gnb_context> gc;
if(!is_assoc_id_2_gnb_context(itti_msg.assoc_id)) {
Logger::amf_n2().error("no existed gNB context with assoc_id(%d)",itti_msg.assoc_id);
if (!is_assoc_id_2_gnb_context(itti_msg.assoc_id)) {
Logger::amf_n2().error("No existed gNB context with assoc_id(%d)", itti_msg.assoc_id);
return;
}
gc = assoc_id_2_gnb_context(itti_msg.assoc_id);
if(gc.get()->ng_state == NGAP_RESETING || gc.get()->ng_state == NGAP_SHUTDOWN){
if (gc.get()->ng_state == NGAP_RESETING || gc.get()->ng_state == NGAP_SHUTDOWN) {
Logger::amf_n2().warn("Received new association request on an association that is being %s, ignoring", ng_gnb_state_str[gc.get()->ng_state]);
}else{
} else {
Logger::amf_n2().debug("Update gNB context with assoc id (%d)", itti_msg.assoc_id);
}
gnb_infos gnbItem;
//Get IE Global RAN Node ID
uint32_t gnb_id; string gnb_mcc; string gnb_mnc;
if(!itti_msg.ngSetupReq->getGlobalGnbID(gnb_id, gnb_mcc, gnb_mnc)){
uint32_t gnb_id;
string gnb_mcc;
string gnb_mnc;
if (!itti_msg.ngSetupReq->getGlobalGnbID(gnb_id, gnb_mcc, gnb_mnc)) {
Logger::amf_n2().error("Missing Mandatory IE GlobalGnbID");
return;
}
Logger::amf_n2().debug("IE GlobalGNBID(0x%x)",gnb_id);
Logger::amf_n2().debug("IE GlobalGNBID(0x%x)", gnb_id);
gc->globalRanNodeId = gnb_id;
gnbItem.gnb_id = gnb_id;
string gnb_name;
if(!itti_msg.ngSetupReq->getRanNodeName(gnb_name)){
if (!itti_msg.ngSetupReq->getRanNodeName(gnb_name)) {
Logger::amf_n2().warn("IE RanNodeName not existed");
}else{
} else {
gc->gnb_name = gnb_name;
gnbItem.gnb_name = gnb_name;
Logger::amf_n2().debug("IE RanNodeName(%s)",gnb_name.c_str());
Logger::amf_n2().debug("IE RanNodeName(%s)", gnb_name.c_str());
}
int defPagingDrx = itti_msg.ngSetupReq->getDefaultPagingDRX();
if(defPagingDrx == -1){
Logger::amf_n2().error("Missing Mandontary IE DefaultPagingDRX");
if (defPagingDrx == -1) {
Logger::amf_n2().error("Missing Mandatory IE DefaultPagingDRX");
return;
}
Logger::amf_n2().debug("IE DefaultPagingDRX(%d)",defPagingDrx);
Logger::amf_n2().debug("IE DefaultPagingDRX(%d)", defPagingDrx);
vector<SupportedItem_t> s_ta_list;
if(!itti_msg.ngSetupReq->getSupportedTAList(s_ta_list)){//getSupportedTAList
if (!itti_msg.ngSetupReq->getSupportedTAList(s_ta_list)) { //getSupportedTAList
return;
}
gnbItem.mcc = s_ta_list[0].b_plmn_list[0].mcc;
......@@ -186,30 +204,30 @@ void amf_n2::handle_itti_message(itti_ng_setup_request & itti_msg){
//association GlobalRANNodeID with assoc_id
//store RAN Node Name in gNB context, if present
//verify PLMN Identity and TAC with configuration and store supportedTAList in gNB context, if verified; else response NG SETUP FAILURE with cause "Unknown PLMN"(9.3.1.2, ts38413)
if(!verifyPlmn(s_ta_list)){
if (!verifyPlmn(s_ta_list)) {
//encode NG SETUP FAILURE MESSAGE and send back
void *buffer = calloc(1,1000);
void *buffer = calloc(1, 1000);
NGSetupFailureMsg ngSetupFailure;
ngSetupFailure.setMessageType();
ngSetupFailure.setCauseRadioNetwork(Ngap_CauseRadioNetwork_unspecified,Ngap_TimeToWait_v5s);
int encoded = ngSetupFailure.encode2buffer((uint8_t*)buffer,1000);
ngSetupFailure.setCauseRadioNetwork(Ngap_CauseRadioNetwork_unspecified, Ngap_TimeToWait_v5s);
int encoded = ngSetupFailure.encode2buffer((uint8_t*) buffer, 1000);
bstring b = blk2bstr(buffer, encoded);
sctp_s_38412.sctp_send_msg(itti_msg.assoc_id,itti_msg.stream ,&b);
Logger::amf_n2().error("no common plmn, encoding NG_SETUP_FAILURE with cause( Unknown PLMN )");
sctp_s_38412.sctp_send_msg(itti_msg.assoc_id, itti_msg.stream, &b);
Logger::amf_n2().error("No common plmn, encoding NG_SETUP_FAILURE with cause( Unknown PLMN )");
return;
}else{
} else {
gc->s_ta_list = s_ta_list;
}
//store Paging DRX in gNB context
Logger::amf_n2().debug("encoding NG_SETUP_RESPONSE ...");
Logger::amf_n2().debug("Encoding NG_SETUP_RESPONSE ...");
//encode NG SETUP RESPONSE message with information stored in configuration file and send_msg
void *buffer = calloc(1,1000);
void *buffer = calloc(1, 1000);
NGSetupResponseMsg ngSetupResp;
ngSetupResp.setMessageType();
ngSetupResp.setAMFName(amf_cfg.AMF_Name);
ngSetupResp.setRelativeAmfCapacity(amf_cfg.relativeAMFCapacity);
std::vector<struct GuamiItem_s> guami_list;
for(int i=0; i< amf_cfg.guami_list.size(); i++){
for (int i = 0; i < amf_cfg.guami_list.size(); i++) {
struct GuamiItem_s tmp;
tmp.mcc = amf_cfg.guami_list[i].mcc;
tmp.mnc = amf_cfg.guami_list[i].mnc;
......@@ -221,11 +239,11 @@ void amf_n2::handle_itti_message(itti_ng_setup_request & itti_msg){
}
ngSetupResp.setGUAMIList(guami_list);
std::vector<PlmnSliceSupport_t> plmn_list;
for(int i=0; i<amf_cfg.plmn_list.size(); i++){
for (int i = 0; i < amf_cfg.plmn_list.size(); i++) {
PlmnSliceSupport_t tmp;
tmp.mcc = amf_cfg.plmn_list[i].mcc;
tmp.mnc = amf_cfg.plmn_list[i].mnc;
for(int j=0; j<amf_cfg.plmn_list[i].slice_list.size(); j++){
for (int j = 0; j < amf_cfg.plmn_list[i].slice_list.size(); j++) {
SliceSupportItem_t s_tmp;
s_tmp.sst = amf_cfg.plmn_list[i].slice_list[j].sST;
s_tmp.sd = amf_cfg.plmn_list[i].slice_list[j].sD;
......@@ -234,77 +252,76 @@ void amf_n2::handle_itti_message(itti_ng_setup_request & itti_msg){
plmn_list.push_back(tmp);
}
ngSetupResp.setPlmnSupportList(plmn_list);
int encoded = ngSetupResp.encode2buffer((uint8_t*)buffer,1000);
int encoded = ngSetupResp.encode2buffer((uint8_t*) buffer, 1000);
bstring b = blk2bstr(buffer, encoded);
sctp_s_38412.sctp_send_msg(itti_msg.assoc_id,itti_msg.stream ,&b);
Logger::amf_n2().debug("sending NG_SETUP_RESPONSE ok");
sctp_s_38412.sctp_send_msg(itti_msg.assoc_id, itti_msg.stream, &b);
Logger::amf_n2().debug("Sending NG_SETUP_RESPONSE ok");
gc.get()->ng_state = NGAP_READY;
Logger::amf_n2().debug("gnb with [gnb_id(0x%x), assoc_id(%d)] has been attached to AMF", gc.get()->globalRanNodeId, itti_msg.assoc_id);
Logger::amf_n2().debug("gNB with [gnb_id(0x%x), assoc_id(%d)] has been attached to AMF", gc.get()->globalRanNodeId, itti_msg.assoc_id);
stacs.gNB_connected += 1;
stacs.gnbs.push_back(gnbItem);
return;
}
/************************* INITIAL_UE_MESSAGE Handler **************************/
void amf_n2::handle_itti_message(itti_initial_ue_message &init_ue_msg){
//------------------------------------------------------------------------------
//INITIAL_UE_MESSAGE Handler
void amf_n2::handle_itti_message(itti_initial_ue_message &init_ue_msg) {
//create ngap-ue context and store in gNB context to store UE information in gNB, for example, here RAN UE NGAP ID and location information and RRC Establishment Cause
//send NAS-PDU to NAS layer
/*get INITIAL_UE_MESSAGE IEs*/
//check the gNB context on which this UE is attached with assoc_id
itti_nas_signalling_establishment_request *itti_msg = new itti_nas_signalling_establishment_request(TASK_AMF_N2, TASK_AMF_APP);
itti_nas_signalling_establishment_request * itti_msg = new itti_nas_signalling_establishment_request(TASK_AMF_N2, TASK_AMF_APP);
if(!is_assoc_id_2_gnb_context(init_ue_msg.assoc_id)) {
Logger::amf_n2().error("no existed gnb context with assoc_id(%d)",init_ue_msg.assoc_id);
if (!is_assoc_id_2_gnb_context(init_ue_msg.assoc_id)) {
Logger::amf_n2().error("No existed gNG context with assoc_id(%d)", init_ue_msg.assoc_id);
return;
}
std::shared_ptr<gnb_context> gc;
gc = assoc_id_2_gnb_context(init_ue_msg.assoc_id);
if(gc.get()->ng_state == NGAP_RESETING || gc.get()->ng_state == NGAP_SHUTDOWN){
if (gc.get()->ng_state == NGAP_RESETING || gc.get()->ng_state == NGAP_SHUTDOWN) {
Logger::amf_n2().warn("Received new association request on an association that is being %s, ignoring", ng_gnb_state_str[gc.get()->ng_state]);
}else if(gc.get()->ng_state != NGAP_READY){
} else if (gc.get()->ng_state != NGAP_READY) {
Logger::amf_n2().debug("gNB with assoc_id(%d) is illegal", init_ue_msg.assoc_id);
return;
}
uint32_t ran_ue_ngap_id;
if( (ran_ue_ngap_id = init_ue_msg.initUeMsg->getRanUENgapID()) == -1){
if ((ran_ue_ngap_id = init_ue_msg.initUeMsg->getRanUENgapID()) == -1) {
Logger::amf_n2().error("Missing Mandatory IE (RanUeNgapId)");
return;
}
std::shared_ptr<ue_ngap_context> unc;
if(!is_ran_ue_id_2_ne_ngap_context(ran_ue_ngap_id)){
Logger::amf_n2().debug("Create a new ue ngap context with ran_ue_ngap_id(0x%x)", ran_ue_ngap_id);
unc = std::shared_ptr<ue_ngap_context>(new ue_ngap_context());
if (!is_ran_ue_id_2_ne_ngap_context(ran_ue_ngap_id)) {
Logger::amf_n2().debug("Create a new UE NGAP context with ran_ue_ngap_id(0x%x)", ran_ue_ngap_id);
unc = std::shared_ptr < ue_ngap_context > (new ue_ngap_context());
set_ran_ue_ngap_id_2_ue_ngap_context(ran_ue_ngap_id, unc);
}else{
} else {
unc = ran_ue_id_2_ue_ngap_context(ran_ue_ngap_id);
}
if(unc.get() == nullptr){
Logger::amf_n2().error("Failed to get ue ngap context for ran_ue_ngap_id(0x%x)",21);
}else{
//store information into ue ngap context
if (unc.get() == nullptr) {
Logger::amf_n2().error("Failed to get UE NGAP context for ran_ue_ngap_id(0x%x)", 21);
} else {
//store information into UE NGAP context
unc.get()->ran_ue_ngap_id = ran_ue_ngap_id;
unc.get()->sctp_stream_recv = init_ue_msg.stream;
unc.get()->sctp_stream_send == gc.get()->next_sctp_stream;
gc.get()->next_sctp_stream += 1;
if(gc.get()->next_sctp_stream >= gc.get()->instreams)
if (gc.get()->next_sctp_stream >= gc.get()->instreams)
gc.get()->next_sctp_stream = 1;
unc.get()->gnb_assoc_id = init_ue_msg.assoc_id;
NrCgi_t cgi;
Tai_t tai;
if(init_ue_msg.initUeMsg->getUserLocationInfoNR(cgi, tai)){
if (init_ue_msg.initUeMsg->getUserLocationInfoNR(cgi, tai)) {
itti_msg->cgi = cgi;
itti_msg->tai = tai;
}else{
} else {
Logger::amf_n2().error("Missing Mandatory IE UserLocationInfoNR");
return;
}
if(init_ue_msg.initUeMsg->getRRCEstablishmentCause() == -1){
if (init_ue_msg.initUeMsg->getRRCEstablishmentCause() == -1) {
Logger::amf_n2().warn("IE RRCEstablishmentCause not present");
itti_msg->rrc_cause = -1;//not present
}else{
itti_msg->rrc_cause = -1; //not present
} else {
itti_msg->rrc_cause = init_ue_msg.initUeMsg->getRRCEstablishmentCause();
}
#if 0
......@@ -317,10 +334,10 @@ void amf_n2::handle_itti_message(itti_initial_ue_message &init_ue_msg){
}
#endif
std::string _5g_s_tmsi;
if(!init_ue_msg.initUeMsg->get5GS_TMSI(_5g_s_tmsi)){
if (!init_ue_msg.initUeMsg->get5GS_TMSI(_5g_s_tmsi)) {
itti_msg->is_5g_s_tmsi_present = false;
Logger::amf_n2().debug("5g_s_tmsi false");
}else{
} else {
itti_msg->is_5g_s_tmsi_present = true;
itti_msg->_5g_s_tmsi = _5g_s_tmsi;
Logger::amf_n2().debug("5g_s_tmsi true");
......@@ -328,10 +345,10 @@ void amf_n2::handle_itti_message(itti_initial_ue_message &init_ue_msg){
uint8_t *nas_buf;
size_t nas_len = 0;
if(init_ue_msg.initUeMsg->getNasPdu(nas_buf,nas_len)){
if (init_ue_msg.initUeMsg->getNasPdu(nas_buf, nas_len)) {
bstring nas = blk2bstr(nas_buf, nas_len);
itti_msg->nas_buf = nas;
}else{
} else {
Logger::amf_n2().error("Missing IE NAS-PDU");
return;
}
......@@ -339,70 +356,72 @@ void amf_n2::handle_itti_message(itti_initial_ue_message &init_ue_msg){
}
itti_msg->ran_ue_ngap_id = ran_ue_ngap_id;
itti_msg->amf_ue_ngap_id = -1;
std::shared_ptr<itti_nas_signalling_establishment_request> i = std::shared_ptr<itti_nas_signalling_establishment_request>(itti_msg);
std::shared_ptr<itti_nas_signalling_establishment_request> i = std::shared_ptr < itti_nas_signalling_establishment_request > (itti_msg);
int ret = itti_inst->send_msg(i);
if (0 != ret) {
Logger::amf_n2().error( "Could not send ITTI message %s to task TASK_AMF_APP", i->get_msg_name());
Logger::amf_n2().error("Could not send ITTI message %s to task TASK_AMF_APP", i->get_msg_name());
}
}
void amf_n2::handle_itti_message(itti_ul_nas_transport &ul_nas_transport){
//------------------------------------------------------------------------------
void amf_n2::handle_itti_message(itti_ul_nas_transport &ul_nas_transport) {
unsigned long amf_ue_ngap_id = ul_nas_transport.ulNas->getAmfUeNgapId();
uint32_t ran_ue_ngap_id = ul_nas_transport.ulNas->getRanUeNgapId();
std::shared_ptr<gnb_context>gc;
if(!is_assoc_id_2_gnb_context(ul_nas_transport.assoc_id)){
Logger::amf_n2().error("gnb with assoc_id(%d) is illegal",ul_nas_transport.assoc_id);
std::shared_ptr<gnb_context> gc;
if (!is_assoc_id_2_gnb_context(ul_nas_transport.assoc_id)) {
Logger::amf_n2().error("gNB with assoc_id(%d) is illegal", ul_nas_transport.assoc_id);
return;
}
gc = assoc_id_2_gnb_context(ul_nas_transport.assoc_id);
std::shared_ptr<ue_ngap_context> unc;
if(!is_ran_ue_id_2_ne_ngap_context(ran_ue_ngap_id)){
if (!is_ran_ue_id_2_ne_ngap_context(ran_ue_ngap_id)) {
Logger::amf_n2().error("UE with ran_ue_ngap_id(0x%x) is not attached to gnb with assoc_id(%d)", ran_ue_ngap_id, ul_nas_transport.assoc_id);
return;
}
if(!is_ran_ue_id_2_ne_ngap_context(ran_ue_ngap_id)){
Logger::amf_n2().error("no ue ngap context with ran_ue_ngap_id(%d)", ran_ue_ngap_id);
if (!is_ran_ue_id_2_ne_ngap_context(ran_ue_ngap_id)) {
Logger::amf_n2().error("No UE NGAP context with ran_ue_ngap_id(%d)", ran_ue_ngap_id);
return;
}
unc = ran_ue_id_2_ue_ngap_context(ran_ue_ngap_id);
if(unc.get()->amf_ue_ngap_id != amf_ue_ngap_id){
if (unc.get()->amf_ue_ngap_id != amf_ue_ngap_id) {
Logger::amf_n2().error("The requested UE(amf_ue_ngap_id:0x%x) is not valid, existed UE which's amf_ue_ngap_id(0x%x)", amf_ue_ngap_id, unc.get()->amf_ue_ngap_id);
}
if(unc.get()->ng_ue_state != NGAP_UE_CONNECTED){
if (unc.get()->ng_ue_state != NGAP_UE_CONNECTED) {
Logger::amf_n2().error("Received NGAP UPLINK_NAS_TRANSPORT while UE in state != NGAP_UE_CONNECTED");
//return;
}
itti_uplink_nas_data_ind * itti_msg = new itti_uplink_nas_data_ind(TASK_AMF_N2, TASK_AMF_N1);
itti_uplink_nas_data_ind *itti_msg = new itti_uplink_nas_data_ind(TASK_AMF_N2, TASK_AMF_N1);
itti_msg->is_nas_signalling_estab_req = false;
itti_msg->amf_ue_ngap_id = amf_ue_ngap_id;
itti_msg->ran_ue_ngap_id = ran_ue_ngap_id;
itti_msg->is_guti_valid = false;
uint8_t *nas_buf = NULL;
size_t nas_len = 0;
if(ul_nas_transport.ulNas->getNasPdu(nas_buf, nas_len)){
if (ul_nas_transport.ulNas->getNasPdu(nas_buf, nas_len)) {
itti_msg->nas_msg = blk2bstr(nas_buf, nas_len);
}else{
} else {
Logger::amf_n2().error("Missing IE NAS-PDU");
return;
}
std::shared_ptr<itti_uplink_nas_data_ind> i = std::shared_ptr<itti_uplink_nas_data_ind>(itti_msg);
std::shared_ptr<itti_uplink_nas_data_ind> i = std::shared_ptr < itti_uplink_nas_data_ind > (itti_msg);
int ret = itti_inst->send_msg(i);
if (0 != ret) {
Logger::amf_n2().error( "Could not send ITTI message %s to task TASK_AMF_N1", i->get_msg_name());
Logger::amf_n2().error("Could not send ITTI message %s to task TASK_AMF_N1", i->get_msg_name());
}
}
void amf_n2::handle_itti_message(itti_dl_nas_transport &dl_nas_transport){
//------------------------------------------------------------------------------
void amf_n2::handle_itti_message(itti_dl_nas_transport &dl_nas_transport) {
std::shared_ptr<ue_ngap_context> unc;
unc = ran_ue_id_2_ue_ngap_context(dl_nas_transport.ran_ue_ngap_id);
if(unc.get() == nullptr){
Logger::amf_n2().error("Illegal ue with ran_ue_ngap_id(0x%x)", dl_nas_transport.ran_ue_ngap_id);
if (unc.get() == nullptr) {
Logger::amf_n2().error("Illegal UE with ran_ue_ngap_id(0x%x)", dl_nas_transport.ran_ue_ngap_id);
return;
}
std::shared_ptr<gnb_context> gc;
gc = assoc_id_2_gnb_context(unc.get()->gnb_assoc_id);
if(gc.get() == nullptr){
Logger::amf_n2().error("Illegal gnb with assoc id(0x%x)", unc.get()->gnb_assoc_id);
if (gc.get() == nullptr) {
Logger::amf_n2().error("Illegal gNB with assoc id(0x%x)", unc.get()->gnb_assoc_id);
return;
}
unc.get()->amf_ue_ngap_id = dl_nas_transport.amf_ue_ngap_id;
......@@ -411,27 +430,28 @@ void amf_n2::handle_itti_message(itti_dl_nas_transport &dl_nas_transport){
ngap_msg->setMessageType();
ngap_msg->setAmfUeNgapId(dl_nas_transport.amf_ue_ngap_id);
ngap_msg->setRanUeNgapId(dl_nas_transport.ran_ue_ngap_id);
ngap_msg->setNasPdu((uint8_t*)bdata(dl_nas_transport.nas), blength(dl_nas_transport.nas));
ngap_msg->setNasPdu((uint8_t*) bdata(dl_nas_transport.nas), blength(dl_nas_transport.nas));
uint8_t buffer[1024];
int encoded_size = ngap_msg->encode2buffer(buffer, 1024);
bstring b = blk2bstr(buffer, encoded_size);
sctp_s_38412.sctp_send_msg(gc.get()->sctp_assoc_id, unc.get()->sctp_stream_send,&b);
sctp_s_38412.sctp_send_msg(gc.get()->sctp_assoc_id, unc.get()->sctp_stream_send, &b);
}
void amf_n2::handle_itti_message(itti_initial_context_setup_request &itti_msg){
//------------------------------------------------------------------------------
void amf_n2::handle_itti_message(itti_initial_context_setup_request &itti_msg) {
std::shared_ptr<ue_ngap_context> unc;
unc = ran_ue_id_2_ue_ngap_context(itti_msg.ran_ue_ngap_id);
if(unc.get() == nullptr){
Logger::amf_n2().error("Illegal ue with ran_ue_ngap_id(0x%x)", itti_msg.ran_ue_ngap_id);
if (unc.get() == nullptr) {
Logger::amf_n2().error("Illegal UE with ran_ue_ngap_id(0x%x)", itti_msg.ran_ue_ngap_id);
return;
}
std::shared_ptr<gnb_context> gc;
gc = assoc_id_2_gnb_context(unc.get()->gnb_assoc_id);
if(gc.get() == nullptr){
Logger::amf_n2().error("Illegal gnb with assoc id(0x%x)", unc.get()->gnb_assoc_id);
if (gc.get() == nullptr) {
Logger::amf_n2().error("Illegal gNB with assoc id(0x%x)", unc.get()->gnb_assoc_id);
return;
}
InitialContextSetupRequestMsg * msg = new InitialContextSetupRequestMsg();
InitialContextSetupRequestMsg *msg = new InitialContextSetupRequestMsg();
msg->setMessageType();
msg->setAmfUeNgapId(itti_msg.amf_ue_ngap_id);
msg->setRanUeNgapId(itti_msg.ran_ue_ngap_id);
......@@ -443,29 +463,28 @@ void amf_n2::handle_itti_message(itti_initial_context_setup_request &itti_msg){
guami.AmfPointer = amf_cfg.guami.AmfPointer;
msg->setGuami(guami);
msg->setUESecurityCapability(0xe000, 0xe000, 0xe000, 0xe000);
msg->setSecurityKey((uint8_t*)bdata(itti_msg.kgnb));
msg->setNasPdu((uint8_t*)bdata(itti_msg.nas), blength(itti_msg.nas));
msg->setSecurityKey((uint8_t*) bdata(itti_msg.kgnb));
msg->setNasPdu((uint8_t*) bdata(itti_msg.nas), blength(itti_msg.nas));
if(itti_msg.is_sr){
if (itti_msg.is_sr) {
bstring ueCapability = gc.get()->ue_radio_cap_ind;
uint8_t *uecap = (uint8_t*)calloc(1, blength(ueCapability)+1);
memcpy(uecap, (uint8_t*)bdata(ueCapability), blength(ueCapability));
uint8_t *uecap = (uint8_t*) calloc(1, blength(ueCapability) + 1);
memcpy(uecap, (uint8_t*) bdata(ueCapability), blength(ueCapability));
uecap[blength(ueCapability)] = '\0';
msg->setUERadioCapability(uecap, (size_t)blength(ueCapability));
//msg->setUERadioCapability((uint8_t*)bdata(ueCapability), (size_t)blength(ueCapability));
Logger::amf_n2().debug("Encoding parameters for service request");
std::vector<PDUSessionResourceSetupRequestItem_t>list;
std::vector<PDUSessionResourceSetupRequestItem_t> list;
PDUSessionResourceSetupRequestItem_t item;
item.pduSessionId = itti_msg.pdu_session_id;
item.s_nssai.sst = "01";
item.s_nssai.sd = "";
item.pduSessionNAS_PDU = NULL;
bstring n2sm = itti_msg.n2sm;
if(blength(itti_msg.n2sm) != 0){
item.pduSessionResourceSetupRequestTransfer.buf = (uint8_t*)bdata(itti_msg.n2sm);
if (blength(itti_msg.n2sm) != 0) {
item.pduSessionResourceSetupRequestTransfer.buf = (uint8_t*) bdata(itti_msg.n2sm);
item.pduSessionResourceSetupRequestTransfer.size = blength(itti_msg.n2sm);
}else{
} else {
Logger::amf_n2().error("n2sm empty!");
}
list.push_back(item);
......@@ -476,23 +495,24 @@ void amf_n2::handle_itti_message(itti_initial_context_setup_request &itti_msg){
uint8_t buffer[10000];
int encoded_size = msg->encode2buffer(buffer, 10000);
bstring b = blk2bstr(buffer, encoded_size);
sctp_s_38412.sctp_send_msg(gc.get()->sctp_assoc_id, unc.get()->sctp_stream_send,&b);
sctp_s_38412.sctp_send_msg(gc.get()->sctp_assoc_id, unc.get()->sctp_stream_send, &b);
}
void amf_n2::handle_itti_message(itti_pdu_session_resource_setup_request &itti_msg){
//------------------------------------------------------------------------------
void amf_n2::handle_itti_message(itti_pdu_session_resource_setup_request &itti_msg) {
std::shared_ptr<ue_ngap_context> unc;
unc = ran_ue_id_2_ue_ngap_context(itti_msg.ran_ue_ngap_id);
if(unc.get() == nullptr){
Logger::amf_n2().error("Illegal ue with ran_ue_ngap_id(0x%x)", itti_msg.ran_ue_ngap_id);
if (unc.get() == nullptr) {
Logger::amf_n2().error("Illegal UE with ran_ue_ngap_id(0x%x)", itti_msg.ran_ue_ngap_id);
return;
}
std::shared_ptr<gnb_context> gc;
gc = assoc_id_2_gnb_context(unc.get()->gnb_assoc_id);
if(gc.get() == nullptr){
Logger::amf_n2().error("Illegal gnb with assoc id(0x%x)", unc.get()->gnb_assoc_id);
if (gc.get() == nullptr) {
Logger::amf_n2().error("Illegal gNB with assoc id(0x%x)", unc.get()->gnb_assoc_id);
return;
}
PduSessionResourceSetupRequestMsg * psrsr = new PduSessionResourceSetupRequestMsg();
PduSessionResourceSetupRequestMsg *psrsr = new PduSessionResourceSetupRequestMsg();
psrsr->setMessageType();
psrsr->setAmfUeNgapId(itti_msg.amf_ue_ngap_id);
psrsr->setRanUeNgapId(itti_msg.ran_ue_ngap_id);
......@@ -500,14 +520,14 @@ void amf_n2::handle_itti_message(itti_pdu_session_resource_setup_request &itti_m
std::vector<PDUSessionResourceSetupRequestItem_t> list;
PDUSessionResourceSetupRequestItem_t item;
item.pduSessionId = itti_msg.pdu_session_id;
uint8_t *nas_pdu = (uint8_t*)calloc(1, blength(itti_msg.nas)+1);
memcpy(nas_pdu, (uint8_t*)bdata(itti_msg.nas), blength(itti_msg.nas));
uint8_t *nas_pdu = (uint8_t*) calloc(1, blength(itti_msg.nas) + 1);
memcpy(nas_pdu, (uint8_t*) bdata(itti_msg.nas), blength(itti_msg.nas));
nas_pdu[blength(itti_msg.nas)] = '\0';
item.pduSessionNAS_PDU = nas_pdu;//(uint8_t*)bdata(itti_msg.nas);
item.pduSessionNAS_PDU = nas_pdu;
item.sizeofpduSessionNAS_PDU = blength(itti_msg.nas);
item.s_nssai.sst = "01";
item.s_nssai.sd = "";
item.pduSessionResourceSetupRequestTransfer.buf = (uint8_t*)bdata(itti_msg.n2sm);
item.pduSessionResourceSetupRequestTransfer.buf = (uint8_t*) bdata(itti_msg.n2sm);
item.pduSessionResourceSetupRequestTransfer.size = blength(itti_msg.n2sm);
list.push_back(item);
psrsr->setPduSessionResourceSetupRequestList(list);
......@@ -515,16 +535,17 @@ void amf_n2::handle_itti_message(itti_pdu_session_resource_setup_request &itti_m
uint8_t buffer[5000];
int encoded_size = psrsr->encode2buffer(buffer, 5000);
bstring b = blk2bstr(buffer, encoded_size);
sctp_s_38412.sctp_send_msg(gc.get()->sctp_assoc_id, unc.get()->sctp_stream_send,&b);
sctp_s_38412.sctp_send_msg(gc.get()->sctp_assoc_id, unc.get()->sctp_stream_send, &b);
}
void amf_n2::handle_itti_message(itti_ue_context_release_request &itti_msg){
Logger::amf_n2().debug("handling ue context release request ...");
//------------------------------------------------------------------------------
void amf_n2::handle_itti_message(itti_ue_context_release_request &itti_msg) {
Logger::amf_n2().debug("Handling UE context release request ...");
unsigned long amf_ue_ngap_id = itti_msg.ueCtxRel->getAmfUeNgapId();
uint32_t ran_ue_ngap_id = itti_msg.ueCtxRel->getRanUeNgapId();
e_Ngap_CauseRadioNetwork cause;
itti_msg.ueCtxRel->getCauseRadioNetwork(cause);
UEContextReleaseCommandMsg * ueCtxRelCmd = new UEContextReleaseCommandMsg();
UEContextReleaseCommandMsg *ueCtxRelCmd = new UEContextReleaseCommandMsg();
ueCtxRelCmd->setMessageType();
ueCtxRelCmd->setUeNgapIdPair(amf_ue_ngap_id, ran_ue_ngap_id);
ueCtxRelCmd->setCauseRadioNetwork(cause);
......@@ -534,48 +555,58 @@ void amf_n2::handle_itti_message(itti_ue_context_release_request &itti_msg){
sctp_s_38412.sctp_send_msg(itti_msg.assoc_id, itti_msg.stream, &b);
}
void amf_n2::handle_itti_message(itti_ue_radio_capability_indication &itti_msg){
//------------------------------------------------------------------------------
void amf_n2::handle_itti_message(itti_ue_radio_capability_indication &itti_msg) {
std::shared_ptr<gnb_context> gc;
if(!is_assoc_id_2_gnb_context(itti_msg.assoc_id)) {
Logger::amf_n2().error("no existed gnb context with assoc_id(%d)",itti_msg.assoc_id);
if (!is_assoc_id_2_gnb_context(itti_msg.assoc_id)) {
Logger::amf_n2().error("No existed gNB context with assoc_id(%d)", itti_msg.assoc_id);
return;
}
gc = assoc_id_2_gnb_context(itti_msg.assoc_id);
unsigned long amf_ue_ngap_id; itti_msg.ueRadioCap->getAmfUeNgapId(amf_ue_ngap_id);
uint32_t ran_ue_ngap_id; itti_msg.ueRadioCap->getRanUeNgapId(ran_ue_ngap_id);
uint8_t *ue_radio_cap; size_t size;
if(!itti_msg.ueRadioCap->getUERadioCapability(ue_radio_cap, size)){
unsigned long amf_ue_ngap_id;
itti_msg.ueRadioCap->getAmfUeNgapId(amf_ue_ngap_id);
uint32_t ran_ue_ngap_id;
itti_msg.ueRadioCap->getRanUeNgapId(ran_ue_ngap_id);
uint8_t *ue_radio_cap;
size_t size;
if (!itti_msg.ueRadioCap->getUERadioCapability(ue_radio_cap, size)) {
Logger::amf_n2().warn("No IE UERadioCapability");
}
gc.get()->ue_radio_cap_ind = blk2bstr(ue_radio_cap, (int)size);
gc.get()->ue_radio_cap_ind = blk2bstr(ue_radio_cap, (int) size);
}
/************************************************* context management functions *********************************/
//Context management functions
//------------------------------------------------------------------------------
bool amf_n2::is_ran_ue_id_2_ne_ngap_context(const uint32_t & ran_ue_ngap_id) const {
bool amf_n2::is_ran_ue_id_2_ne_ngap_context(const uint32_t &ran_ue_ngap_id) const {
std::shared_lock lock(m_ranid2uecontext);
return bool{ranid2uecontext.count(ran_ue_ngap_id) > 0};
return bool { ranid2uecontext.count(ran_ue_ngap_id) > 0 };
}
std::shared_ptr<ue_ngap_context> amf_n2::ran_ue_id_2_ue_ngap_context(const uint32_t & ran_ue_ngap_id) const {
//------------------------------------------------------------------------------
std::shared_ptr<ue_ngap_context> amf_n2::ran_ue_id_2_ue_ngap_context(const uint32_t &ran_ue_ngap_id) const {
std::shared_lock lock(m_ranid2uecontext);
return ranid2uecontext.at(ran_ue_ngap_id);
}
void amf_n2::set_ran_ue_ngap_id_2_ue_ngap_context(const uint32_t & ran_ue_ngap_id, std::shared_ptr<ue_ngap_context> unc){
//------------------------------------------------------------------------------
void amf_n2::set_ran_ue_ngap_id_2_ue_ngap_context(const uint32_t &ran_ue_ngap_id, std::shared_ptr<ue_ngap_context> unc) {
std::shared_lock lock(m_ranid2uecontext);
ranid2uecontext[ran_ue_ngap_id] = unc;
}
/************************************************* internal analysis functions ***********************************/
bool amf_n2::verifyPlmn(vector<SupportedItem_t> list){
for(int i=0; i<amf_cfg.plmn_list.size(); i++){
for(int j=0; j<list.size(); j++){
Logger::amf_n2().debug("tac configured(%d) -- tac received(%d)",amf_cfg.plmn_list[i].tac, list[j].tac);
if(amf_cfg.plmn_list[i].tac != list[j].tac){ continue;}
for(int k=0; k< list[j].b_plmn_list.size();k++){
if(!(list[j].b_plmn_list[k].mcc.compare(amf_cfg.plmn_list[i].mcc)) && !(list[j].b_plmn_list[k].mnc.compare(amf_cfg.plmn_list[i].mnc))){
//------------------------------------------------------------------------------
// internal analysis functions
bool amf_n2::verifyPlmn(vector<SupportedItem_t> list) {
for (int i = 0; i < amf_cfg.plmn_list.size(); i++) {
for (int j = 0; j < list.size(); j++) {
Logger::amf_n2().debug("tac configured(%d) -- tac received(%d)", amf_cfg.plmn_list[i].tac, list[j].tac);
if (amf_cfg.plmn_list[i].tac != list[j].tac) {
continue;
}
for (int k = 0; k < list[j].b_plmn_list.size(); k++) {
if (!(list[j].b_plmn_list[k].mcc.compare(amf_cfg.plmn_list[i].mcc)) && !(list[j].b_plmn_list[k].mnc.compare(amf_cfg.plmn_list[i].mnc))) {
return true;
}
}
......
......@@ -36,7 +36,7 @@
namespace amf_application{
class amf_n2 : public ngap::ngap_app{
public:
public:
amf_n2(const string &address, const uint16_t port_num);
~amf_n2();
//void handle_receive(bstring payload, sctp_assoc_id_t assoc_id, sctp_stream_id_t stream, sctp_stream_id_t instreams, sctp_stream_id_t outstreams);
......@@ -50,7 +50,7 @@ public:
void handle_itti_message(itti_ue_context_release_request &itti_msg);
void handle_itti_message(itti_ue_radio_capability_indication &itti_msg);
bool verifyPlmn(vector<SupportedItem_t> list);
private:
private:
std::map<uint32_t, std::shared_ptr<ue_ngap_context>> ranid2uecontext;// ran ue ngap id
mutable std::shared_mutex m_ranid2uecontext;
......@@ -59,13 +59,6 @@ private:
void set_ran_ue_ngap_id_2_ue_ngap_context(const uint32_t & ran_ue_ngap_id, std::shared_ptr<ue_ngap_context> unc);
};
}
......@@ -81,6 +74,4 @@ private:
#endif
......@@ -31,36 +31,41 @@
#include <iostream>
using namespace std;
void statistics::display(){
cout<<endl;
//------------------------------------------------------------------------------
void statistics::display() {
cout << endl;
//Logger::amf_app().info("--------------------------------------------------");
//Logger::amf_app().info("| connected gNBs | connected UEs | registred UEs |");
//Logger::amf_app().info("| connected gNBs | connected UEs | registered UEs |");
//Logger::amf_app().info("--------------------------------------------------");
//Logger::amf_app().info("| %d | %d | %d |",gNB_connected,UE_connected,UE_registred);
//Logger::amf_app().info("--------------------------------------------------");
Logger::amf_app().info("|--------------------------------------------------------------------------------------------------------------------|");
Logger::amf_app().info("-----------------------------------------------------------------------------------------------------------------");
Logger::amf_app().info("|-----------------------------------------------------------------------------------------------------------------|");
Logger::amf_app().info("|----------------------------------------------------gNBs' information--------------------------------------------|");
for(int i=0; i<gnbs.size(); i++){
Logger::amf_app().info("[index %d][connected][GlobalID: 0x%x][gnb name: %s][Tracking Area: plmn(%s), tac(%d)]", i+1, gnbs[i].gnb_id, gnbs[i].gnb_name.c_str(), (gnbs[i].mcc+gnbs[i].mnc).c_str(), gnbs[i].tac);
for (int i = 0; i < gnbs.size(); i++) {
Logger::amf_app().info("[index %d][connected][GlobalID: 0x%x][gnb name: %s][Tracking Area: plmn(%s), tac(%d)]", i + 1, gnbs[i].gnb_id, gnbs[i].gnb_name.c_str(), (gnbs[i].mcc + gnbs[i].mnc).c_str(), gnbs[i].tac);
}
Logger::amf_app().info("-----------------------------------------------------------------------------------------------------------------"); cout<<endl;
Logger::amf_app().info("-----------------------------------------------------------------------------------------------------------------");
Logger::amf_app().info("");
Logger::amf_app().info("|----------------------------------------------------------------------------------------------------------------|");
Logger::amf_app().info("|----------------------------------------------------UEs' information--------------------------------------------|");
for(int i=0; i<ues.size();i++){
Logger::amf_app().info("[index %d][%s][%s][imsi %s][guti %s]", i+1, ues[i].connStatus.c_str(), ues[i].registerStatus.c_str(), ues[i].imsi.c_str(), ues[i].guti.c_str());
for (int i = 0; i < ues.size(); i++) {
Logger::amf_app().info("[index %d][%s][%s][imsi %s][guti %s]", i + 1, ues[i].connStatus.c_str(), ues[i].registerStatus.c_str(), ues[i].imsi.c_str(), ues[i].guti.c_str());
Logger::amf_app().info("Current ran_ue_ngap_id[%d]; Current amf_ue_ngap_id[%d]", ues[i].ranid, ues[i].amfid);
Logger::amf_app().info("Location[NrCgi][PLMN(%s), cellID(%d)]", (ues[i].mcc+ues[i].mnc).c_str(), ues[i].cellId); cout<<endl;
Logger::amf_app().info("Location[NrCgi][PLMN(%s), cellID(%d)]", (ues[i].mcc + ues[i].mnc).c_str(), ues[i].cellId);
Logger::amf_app().info("");
}
Logger::amf_app().info("-----------------------------------------------------------------------------------------------------------------");
Logger::amf_app().info("|--------------------------------------------------------------------------------------------------------------------|"); cout<<endl;
Logger::amf_app().info("|--------------------------------------------------------------------------------------------------------------------|");
Logger::amf_app().info("");
}
statistics::statistics(){
//------------------------------------------------------------------------------
statistics::statistics() {
gNB_connected = 0;
UE_connected = 0;
UE_registred = 0;
}
statistics::~statistics(){}
//------------------------------------------------------------------------------
statistics::~statistics() {
}
......@@ -37,16 +37,16 @@
using namespace std;
typedef struct{
typedef struct {
uint32_t gnb_id;
string mcc;
string mnc;
string gnb_name;
uint32_t tac;
//long nrCellId;
}gnb_infos;
} gnb_infos;
typedef struct{
typedef struct {
string connStatus;
string registerStatus;
uint32_t ranid;
......@@ -56,14 +56,14 @@ typedef struct{
string mcc;
string mnc;
uint32_t cellId;
}ue_infos;
} ue_infos;
class statistics{
public:
class statistics {
public:
void display();
statistics();
~statistics();
public:
public:
uint32_t gNB_connected;
uint32_t UE_connected;
uint32_t UE_registred;
......@@ -73,11 +73,4 @@ public:
};
#endif
......@@ -34,34 +34,35 @@ using namespace config;
extern amf_config amf_cfg;
bool amf_n1::get_mysql_auth_info(std::string imsi, mysql_auth_info_t &resp){//openair-cn/tree/v0.5.0/src/oai_hss/db/db_connector.c
//------------------------------------------------------------------------------
bool amf_n1::get_mysql_auth_info(std::string imsi, mysql_auth_info_t &resp) { //openair-cn/tree/v0.5.0/src/oai_hss/db/db_connector.c
MYSQL_RES *res;
MYSQL_ROW row;
std::string query;
if(!db_desc->db_conn){
if (!db_desc->db_conn) {
Logger::amf_n1().error("Cannot connect to mysql db");
return false;
}
query = "SELECT `key`,`sqn`,`rand`,`OPc` FROM `users` WHERE `users`.`imsi`='"+imsi+"' ";
pthread_mutex_lock (&db_desc->db_cs_mutex);
if(mysql_query(db_desc->db_conn, query.c_str())){
pthread_mutex_unlock (&db_desc->db_cs_mutex);
Logger::amf_n1().error("Query execution failed: %s\n", mysql_error (db_desc->db_conn));
query = "SELECT `key`,`sqn`,`rand`,`OPc` FROM `users` WHERE `users`.`imsi`='" + imsi + "' ";
pthread_mutex_lock(&db_desc->db_cs_mutex);
if (mysql_query(db_desc->db_conn, query.c_str())) {
pthread_mutex_unlock(&db_desc->db_cs_mutex);
Logger::amf_n1().error("Query execution failed: %s\n", mysql_error(db_desc->db_conn));
return false;
}
res = mysql_store_result (db_desc->db_conn);
pthread_mutex_unlock (&db_desc->db_cs_mutex);
if(!res){
res = mysql_store_result(db_desc->db_conn);
pthread_mutex_unlock(&db_desc->db_cs_mutex);
if (!res) {
Logger::amf_n1().error("data fetched from mysql is not present");
return false;
}
if(row = mysql_fetch_row(res)){
if(row[0] == NULL || row[1] == NULL || row[2] == NULL || row[3] == NULL){
if (row = mysql_fetch_row(res)) {
if (row[0] == NULL || row[1] == NULL || row[2] == NULL || row[3] == NULL) {
Logger::amf_n1().error("row data failed");
return false;
}
memcpy (resp.key, row[0], KEY_LENGTH);
memcpy(resp.key, row[0], KEY_LENGTH);
uint64_t sqn = 0;
sqn = atoll(row[1]);
resp.sqn[0] = (sqn & (255UL << 40)) >> 40;
......@@ -70,84 +71,87 @@ bool amf_n1::get_mysql_auth_info(std::string imsi, mysql_auth_info_t &resp){//op
resp.sqn[3] = (sqn & (255UL << 16)) >> 16;
resp.sqn[4] = (sqn & (255UL << 8)) >> 8;
resp.sqn[5] = (sqn & 0xff);
memcpy (resp.rand, row[2], RAND_LENGTH);
memcpy (resp.opc, row[3], KEY_LENGTH);
memcpy(resp.rand, row[2], RAND_LENGTH);
memcpy(resp.opc, row[3], KEY_LENGTH);
}
mysql_free_result (res);
mysql_free_result(res);
return true;
}
bool amf_n1::connect_to_mysql(){
//------------------------------------------------------------------------------
bool amf_n1::connect_to_mysql() {
const int mysql_reconnect_val = 1;
db_desc = (database_t*)calloc(1, sizeof(database_t));
if(!db_desc){
db_desc = (database_t*) calloc(1, sizeof(database_t));
if (!db_desc) {
Logger::amf_n1().error("An error occurs when calloc");
return false;
}
pthread_mutex_init (&db_desc->db_cs_mutex, NULL);
pthread_mutex_init(&db_desc->db_cs_mutex, NULL);
db_desc->server = amf_cfg.auth_para.mysql_server;
db_desc->user = amf_cfg.auth_para.mysql_user;
db_desc->password = amf_cfg.auth_para.mysql_pass;
db_desc->database = amf_cfg.auth_para.mysql_db;
db_desc->db_conn = mysql_init (NULL);
mysql_options (db_desc->db_conn, MYSQL_OPT_RECONNECT, &mysql_reconnect_val);
if (!mysql_real_connect (db_desc->db_conn, db_desc->server.c_str(), db_desc->user.c_str(), db_desc->password.c_str(), db_desc->database.c_str(), 0, NULL, 0)) {
Logger::amf_n1().error("An error occured while connecting to db: %s", mysql_error (db_desc->db_conn));
db_desc->db_conn = mysql_init(NULL);
mysql_options(db_desc->db_conn, MYSQL_OPT_RECONNECT, &mysql_reconnect_val);
if (!mysql_real_connect(db_desc->db_conn, db_desc->server.c_str(), db_desc->user.c_str(), db_desc->password.c_str(), db_desc->database.c_str(), 0, NULL, 0)) {
Logger::amf_n1().error("An error occurred while connecting to db: %s", mysql_error(db_desc->db_conn));
mysql_thread_end();
return false;
}
mysql_set_server_option (db_desc->db_conn, MYSQL_OPTION_MULTI_STATEMENTS_ON);
mysql_set_server_option(db_desc->db_conn, MYSQL_OPTION_MULTI_STATEMENTS_ON);
return true;
}
void amf_n1::mysql_push_rand_sqn(std::string imsi, uint8_t *rand_p, uint8_t *sqn){
//------------------------------------------------------------------------------
void amf_n1::mysql_push_rand_sqn(std::string imsi, uint8_t *rand_p, uint8_t *sqn) {
int status = 0;
MYSQL_RES *res;
char query[1000];
int query_length = 0;
uint64_t sqn_decimal = 0;
if(!db_desc->db_conn){
if (!db_desc->db_conn) {
Logger::amf_n1().error("Cannot connect to mysql");
return;
}
if(!sqn || !rand_p){
if (!sqn || !rand_p) {
Logger::amf_n1().error("need sqn and rand");
return;
}
sqn_decimal = ((uint64_t) sqn[0] << 40) | ((uint64_t) sqn[1] << 32) | ((uint64_t) sqn[2] << 24) | (sqn[3] << 16) | (sqn[4] << 8) | sqn[5];
query_length = sprintf (query, "UPDATE `users` SET `rand`=UNHEX('");
query_length = sprintf(query, "UPDATE `users` SET `rand`=UNHEX('");
for (int i = 0; i < RAND_LENGTH; i++) {
query_length += sprintf (&query[query_length], "%02x", rand_p[i]);
query_length += sprintf(&query[query_length], "%02x", rand_p[i]);
}
query_length += sprintf (&query[query_length], "'),`sqn`=%" PRIu64, sqn_decimal);
query_length += sprintf (&query[query_length], " WHERE `users`.`imsi`='%s'", imsi.c_str());
pthread_mutex_lock (&db_desc->db_cs_mutex);
if (mysql_query (db_desc->db_conn, query)) {
pthread_mutex_unlock (&db_desc->db_cs_mutex);
Logger::amf_n1().error("Query execution failed: %s", mysql_error (db_desc->db_conn));
query_length += sprintf(&query[query_length], " WHERE `users`.`imsi`='%s'", imsi.c_str());
pthread_mutex_lock(&db_desc->db_cs_mutex);
if (mysql_query(db_desc->db_conn, query)) {
pthread_mutex_unlock(&db_desc->db_cs_mutex);
Logger::amf_n1().error("Query execution failed: %s", mysql_error(db_desc->db_conn));
return;
}
do{
res = mysql_store_result (db_desc->db_conn);
if(res){
mysql_free_result (res);
}else{
if(mysql_field_count (db_desc->db_conn) == 0) {
Logger::amf_n1().error("%lld rows affected", mysql_affected_rows (db_desc->db_conn));
}else{ /* some error occurred */
do {
res = mysql_store_result(db_desc->db_conn);
if (res) {
mysql_free_result(res);
} else {
if (mysql_field_count(db_desc->db_conn) == 0) {
Logger::amf_n1().error("%lld rows affected", mysql_affected_rows(db_desc->db_conn));
} else { /* some error occurred */
Logger::amf_n1().error("Could not retrieve result set");
break;
}
}
if ((status = mysql_next_result (db_desc->db_conn)) > 0)
if ((status = mysql_next_result(db_desc->db_conn)) > 0)
Logger::amf_n1().error("Could not execute statement");
}while(status == 0);
pthread_mutex_unlock (&db_desc->db_cs_mutex);
} while (status == 0);
pthread_mutex_unlock(&db_desc->db_cs_mutex);
return;
}
void amf_n1::mysql_increment_sqn(std::string imsi){
//------------------------------------------------------------------------------
void amf_n1::mysql_increment_sqn(std::string imsi) {
int status;
MYSQL_RES *res;
char query[1000];
......@@ -155,30 +159,30 @@ void amf_n1::mysql_increment_sqn(std::string imsi){
Logger::amf_n1().error("Cannot connect to mysql");
return;
}
sprintf (query, "UPDATE `users` SET `sqn` = `sqn` + 32 WHERE `users`.`imsi`='%s'", imsi.c_str());
sprintf(query, "UPDATE `users` SET `sqn` = `sqn` + 32 WHERE `users`.`imsi`='%s'", imsi.c_str());
pthread_mutex_lock(&db_desc->db_cs_mutex);
if (mysql_query (db_desc->db_conn, query)) {
pthread_mutex_unlock (&db_desc->db_cs_mutex);
Logger::amf_n1().error("Query execution failed: %s", mysql_error (db_desc->db_conn));
if (mysql_query(db_desc->db_conn, query)) {
pthread_mutex_unlock(&db_desc->db_cs_mutex);
Logger::amf_n1().error("Query execution failed: %s", mysql_error(db_desc->db_conn));
return;
}
do{
res = mysql_store_result (db_desc->db_conn);
do {
res = mysql_store_result(db_desc->db_conn);
if (res) {
mysql_free_result (res);
mysql_free_result(res);
} else {
if (mysql_field_count (db_desc->db_conn) == 0) {
Logger::amf_n1().error("%lld rows affected", mysql_affected_rows (db_desc->db_conn));
if (mysql_field_count(db_desc->db_conn) == 0) {
Logger::amf_n1().error("%lld rows affected", mysql_affected_rows(db_desc->db_conn));
} else {
Logger::amf_n1().error("Could not retrieve result set");
break;
}
}
if ((status = mysql_next_result (db_desc->db_conn)) > 0)
if ((status = mysql_next_result(db_desc->db_conn)) > 0)
Logger::amf_n1().error("Could not execute statement");
}while(status == 0);
pthread_mutex_unlock (&db_desc->db_cs_mutex);
} while (status == 0);
pthread_mutex_unlock(&db_desc->db_cs_mutex);
return;
}
......@@ -38,15 +38,15 @@
#define KEY_LENGTH (16)
#define SQN_LENGTH (6)
#define RAND_LENGTH (16)
typedef struct{
typedef struct {
uint8_t key[KEY_LENGTH];
uint8_t sqn[SQN_LENGTH];
uint8_t opc[KEY_LENGTH];
uint8_t rand[RAND_LENGTH];
}mysql_auth_info_t;
} mysql_auth_info_t;
typedef struct {
/* The mysql reference connector object */
//mysql reference connector object
MYSQL *db_conn;
std::string server;
std::string user;
......
......@@ -33,35 +33,37 @@
#include <string>
using namespace std;
void print_buffer(const string app, const string commit, uint8_t *buf, int len){
if(!app.compare("amf_app"))
//------------------------------------------------------------------------------
void print_buffer(const string app, const string commit, uint8_t *buf, int len) {
if (!app.compare("amf_app"))
Logger::amf_app().debug(commit.c_str());
if(!app.compare("amf_n1"))
if (!app.compare("amf_n1"))
Logger::amf_n1().debug(commit.c_str());
if(!app.compare("amf_server"))
if (!app.compare("amf_server"))
Logger::amf_server().debug(commit.c_str());
if(!app.compare("amf_n11"))
if (!app.compare("amf_n11"))
Logger::amf_n11().debug(commit.c_str());
for(int i=0; i<len; i++)
printf("%x ",buf[i]);
for (int i = 0; i < len; i++)
printf("%x ", buf[i]);
printf("\n");
}
void hexStr2Byte(const char* src, unsigned char *dest, int len){
//------------------------------------------------------------------------------
void hexStr2Byte(const char *src, unsigned char *dest, int len) {
short i;
unsigned char hBy, lBy;
for(i=0; i<len; i+=2){
for (i = 0; i < len; i += 2) {
hBy = toupper(src[i]);
lBy = toupper(src[i+1]);
if(hBy > 0x39)
lBy = toupper(src[i + 1]);
if (hBy > 0x39)
hBy -= 0x37;
else
hBy -= 0x30;
if(lBy > 0x39)
if (lBy > 0x39)
lBy -= 0x37;
else
lBy -= 0x30;
dest[i/2] = (hBy<<4) | lBy;
dest[i / 2] = (hBy << 4) | lBy;
}
}
......
......@@ -23,7 +23,7 @@
\brief
\author Sebastien ROUX
\company Eurecom
*/
*/
#include "conversions.hpp"
#include <stdlib.h>
......@@ -33,34 +33,15 @@
#include <inttypes.h>
#include <arpa/inet.h>
static const char hex_to_ascii_table[16] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
};
static const signed char ascii_to_hex_table[0x100] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
};
void conv::hexa_to_ascii (
uint8_t * from,
char *to,
size_t length)
{
static const char hex_to_ascii_table[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', };
static const signed char ascii_to_hex_table[0x100] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
//------------------------------------------------------------------------------
void conv::hexa_to_ascii(uint8_t *from, char *to, size_t length) {
size_t i;
for (i = 0; i < length; i++) {
......@@ -72,18 +53,15 @@ void conv::hexa_to_ascii (
}
}
int conv::ascii_to_hex (
uint8_t * dst,
const char *h)
{
const unsigned char *hex = (const unsigned char *)h;
//------------------------------------------------------------------------------
int conv::ascii_to_hex(uint8_t *dst, const char *h) {
const unsigned char *hex = (const unsigned char*) h;
unsigned i = 0;
for (;;) {
int high,
low;
int high, low;
while (*hex && isspace (*hex))
while (*hex && isspace(*hex))
hex++;
if (!*hex)
......@@ -94,7 +72,7 @@ int conv::ascii_to_hex (
if (high < 0)
return 0;
while (*hex && isspace (*hex))
while (*hex && isspace(*hex))
hex++;
if (!*hex)
......@@ -109,63 +87,57 @@ int conv::ascii_to_hex (
}
}
//------------------------------------------------------------------------------
std::string conv::mccToString(const uint8_t digit1, const uint8_t digit2, const uint8_t digit3)
{
std::string s = {};
uint16_t mcc16 = digit1*100+digit2*10+digit3;
std::string conv::mccToString(const uint8_t digit1, const uint8_t digit2, const uint8_t digit3) {
std::string s = { };
uint16_t mcc16 = digit1 * 100 + digit2 * 10 + digit3;
//s.append(std::to_string(digit1)).append(std::to_string(digit2)).append(std::to_string(digit3));
s.append(std::to_string(mcc16));
return s;
}
//------------------------------------------------------------------------------
std::string conv::mncToString(const uint8_t digit1, const uint8_t digit2, const uint8_t digit3)
{
std::string s = {};
std::string conv::mncToString(const uint8_t digit1, const uint8_t digit2, const uint8_t digit3) {
std::string s = { };
uint16_t mcc16 = 0;
if (digit3 == 0x0F) {
mcc16 = digit1*10+digit2;
mcc16 = digit1 * 10 + digit2;
} else {
mcc16 = digit1*100+digit2*10+digit3;
mcc16 = digit1 * 100 + digit2 * 10 + digit3;
}
s.append(std::to_string(mcc16));
return s;
}
//------------------------------------------------------------------------------
struct in_addr conv::fromString(const std::string addr4)
{
unsigned char buf[sizeof(struct in6_addr)] = {};
struct in_addr conv::fromString(const std::string addr4) {
unsigned char buf[sizeof(struct in6_addr)] = { };
int s = inet_pton(AF_INET, addr4.c_str(), buf);
struct in_addr * ia = (struct in_addr *)buf;
struct in_addr *ia = (struct in_addr*) buf;
return *ia;
}
//------------------------------------------------------------------------------
std::string conv::toString(const struct in_addr& inaddr)
{
std::string s = {};
char str[INET6_ADDRSTRLEN] = {};
if (inet_ntop(AF_INET, (const void *)&inaddr, str, INET6_ADDRSTRLEN) == NULL) {
std::string conv::toString(const struct in_addr &inaddr) {
std::string s = { };
char str[INET6_ADDRSTRLEN] = { };
if (inet_ntop(AF_INET, (const void*) &inaddr, str, INET6_ADDRSTRLEN) == NULL) {
s.append("Error in_addr");
} else {
s.append(str);
}
return s;
}
//------------------------------------------------------------------------------
std::string conv::toString(const struct in6_addr& in6addr)
{
std::string s = {};
char str[INET6_ADDRSTRLEN] = {};
if (inet_ntop(AF_INET6, (const void *)&in6addr, str, INET6_ADDRSTRLEN) == nullptr) {
std::string conv::toString(const struct in6_addr &in6addr) {
std::string s = { };
char str[INET6_ADDRSTRLEN] = { };
if (inet_ntop(AF_INET6, (const void*) &in6addr, str, INET6_ADDRSTRLEN) == nullptr) {
s.append("Error in6_addr");
} else {
s.append(str);
}
return s;
}
......@@ -24,7 +24,7 @@
\author Sebastien ROUX, Lionel Gauthier
\company Eurecom
\email: lionel.gauthier@eurecom.fr
*/
*/
#ifndef FILE_CONVERSIONS_HPP_SEEN
#define FILE_CONVERSIONS_HPP_SEEN
......@@ -32,7 +32,6 @@
#include <string>
#include <netinet/in.h>
/* Used to format an uint32_t containing an ipv4 address */
#define IN_ADDR_FMT "%u.%u.%u.%u"
#define PRI_IN_ADDR(aDDRESS) \
......@@ -44,14 +43,13 @@
#define IPV4_ADDR_DISPLAY_8(aDDRESS) \
(aDDRESS)[0], (aDDRESS)[1], (aDDRESS)[2], (aDDRESS)[3]
class conv {
public:
static void hexa_to_ascii(uint8_t *from, char *to, size_t length);
static int ascii_to_hex(uint8_t *dst, const char *h);
static struct in_addr fromString(const std::string addr4);
static std::string toString(const struct in_addr& inaddr);
static std::string toString(const struct in6_addr& in6addr);
static std::string toString(const struct in_addr &inaddr);
static std::string toString(const struct in6_addr &in6addr);
static std::string mccToString(const uint8_t digit1, const uint8_t digit2, const uint8_t digit3);
static std::string mncToString(const uint8_t digit1, const uint8_t digit2, const uint8_t digit3);
};
......
......@@ -24,7 +24,7 @@
\author Lionel Gauthier
\company Eurecom
\email: lionel.gauthier@eurecom.fr
*/
*/
#ifndef FILE_ENDPOINT_HPP_SEEN
#define FILE_ENDPOINT_HPP_SEEN
......@@ -37,25 +37,39 @@
#include <string.h>
class endpoint {
public :
public:
struct sockaddr_storage addr_storage;
socklen_t addr_storage_len;
endpoint() : addr_storage(), addr_storage_len(sizeof(struct sockaddr_storage)) {};
endpoint(const endpoint& e) : addr_storage(e.addr_storage), addr_storage_len(e.addr_storage_len) {};
endpoint(const struct sockaddr_storage& addr, const socklen_t len) : addr_storage(addr), addr_storage_len(len) {};
endpoint(const struct in_addr& addr, const uint16_t port)
{
struct sockaddr_in * addr_in = (struct sockaddr_in *)&addr_storage;
endpoint()
:
addr_storage(),
addr_storage_len(sizeof(struct sockaddr_storage)) {
}
;
endpoint(const endpoint &e)
:
addr_storage(e.addr_storage),
addr_storage_len(e.addr_storage_len) {
}
;
endpoint(const struct sockaddr_storage &addr, const socklen_t len)
:
addr_storage(addr),
addr_storage_len(len) {
}
;
endpoint(const struct in_addr &addr, const uint16_t port) {
struct sockaddr_in *addr_in = (struct sockaddr_in*) &addr_storage;
addr_in->sin_family = AF_INET;
addr_in->sin_port = htons(port);
addr_in->sin_addr.s_addr = addr.s_addr;
addr_storage_len = sizeof(struct sockaddr_in);
};
}
;
endpoint(const struct in6_addr& addr6, const uint16_t port)
{
struct sockaddr_in6 * addr_in6 = (struct sockaddr_in6 *)&addr_storage;
endpoint(const struct in6_addr &addr6, const uint16_t port) {
struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6*) &addr_storage;
addr_in6->sin6_family = AF_INET6;
addr_in6->sin6_port = htons(port);
addr_in6->sin6_flowinfo = 0;
......@@ -63,28 +77,25 @@ public :
addr_in6->sin6_scope_id = 0;
addr_storage_len = sizeof(struct sockaddr_in6);
};
}
;
uint16_t port() const
{
return ntohs(((struct sockaddr_in *)&addr_storage)->sin_port);
uint16_t port() const {
return ntohs(((struct sockaddr_in*) &addr_storage)->sin_port);
}
sa_family_t family() const
{
sa_family_t family() const {
return addr_storage.ss_family;
}
std::string toString() const
{
std::string toString() const {
std::string str;
if (addr_storage.ss_family == AF_INET) {
struct sockaddr_in * addr_in = (struct sockaddr_in *)&addr_storage;
struct sockaddr_in *addr_in = (struct sockaddr_in*) &addr_storage;
str.append(conv::toString(addr_in->sin_addr));
str.append(":").append(std::to_string(ntohs(addr_in->sin_port)));
}
else if (addr_storage.ss_family == AF_INET6) {
struct sockaddr_in6 * addr_in6 = (struct sockaddr_in6 *)&addr_storage;
} else if (addr_storage.ss_family == AF_INET6) {
struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6*) &addr_storage;
str.append(conv::toString(addr_in6->sin6_addr));
str.append(":").append(std::to_string(ntohs(addr_in6->sin6_port)));
}
......
......@@ -35,7 +35,8 @@
Logger *Logger::m_singleton = NULL;
void Logger::_init(const char *app, const bool log_stdout, const bool log_rot_file){
//------------------------------------------------------------------------------
void Logger::_init(const char *app, const bool log_stdout, const bool log_rot_file) {
int num_sinks = 0;
spdlog::set_async_mode(2048);
#if TRACE_IS_ON
......@@ -48,14 +49,14 @@ void Logger::_init(const char *app, const bool log_stdout, const bool log_rot_fi
spdlog::level::level_enum llevel = spdlog::level::warn;
#endif
if(log_stdout){
std::string filename = fmt::format("./{}.log",app);
if (log_stdout) {
std::string filename = fmt::format("./{}.log", app);
m_sinks.push_back(std::make_shared<spdlog::sinks::ansicolor_stdout_sink_mt>());
m_sinks[num_sinks++].get()->set_level(llevel);
}
if(log_rot_file){
std::string filename = fmt::format("./{}.log",app);
m_sinks.push_back(std::make_shared<spdlog::sinks::rotating_file_sink_mt>(filename, 5*1024*1024, 3));
if (log_rot_file) {
std::string filename = fmt::format("./{}.log", app);
m_sinks.push_back(std::make_shared < spdlog::sinks::rotating_file_sink_mt > (filename, 5 * 1024 * 1024, 3));
}
std::stringstream ss;
......@@ -79,10 +80,11 @@ void Logger::_init(const char *app, const bool log_stdout, const bool log_rot_fi
}
_Logger::_Logger( const char *category, std::vector<spdlog::sink_ptr> &sinks, const char *pattern )
: m_log( category, sinks.begin(), sinks.end() )
{
m_log.set_pattern( pattern );
//------------------------------------------------------------------------------
_Logger::_Logger(const char *category, std::vector<spdlog::sink_ptr> &sinks, const char *pattern)
:
m_log(category, sinks.begin(), sinks.end()) {
m_log.set_pattern(pattern);
#if TRACE_IS_ON
m_log.set_level( spdlog::level::trace );
#elif DEBUG_IS_ON
......@@ -90,12 +92,12 @@ _Logger::_Logger( const char *category, std::vector<spdlog::sink_ptr> &sinks, co
#elif INFO_IS_ON
m_log.set_level( spdlog::level::info );
#else
m_log.set_level( spdlog::level::warn );
m_log.set_level(spdlog::level::warn);
#endif
}
void _Logger::trace( const char *format, ... )
{
//------------------------------------------------------------------------------
void _Logger::trace(const char *format, ...) {
#if TRACE_IS_ON
va_list args;
va_start( args, format );
......@@ -104,8 +106,8 @@ void _Logger::trace( const char *format, ... )
#endif
}
void _Logger::trace( const std::string &format, ... )
{
//------------------------------------------------------------------------------
void _Logger::trace(const std::string &format, ...) {
#if TRACE_IS_ON
va_list args;
va_start( args, format );
......@@ -114,8 +116,8 @@ void _Logger::trace( const std::string &format, ... )
#endif
}
void _Logger::debug( const char *format, ... )
{
//------------------------------------------------------------------------------
void _Logger::debug(const char *format, ...) {
#if DEBUG_IS_ON
va_list args;
va_start( args, format );
......@@ -124,8 +126,8 @@ void _Logger::debug( const char *format, ... )
#endif
}
void _Logger::debug( const std::string &format, ... )
{
//------------------------------------------------------------------------------
void _Logger::debug(const std::string &format, ...) {
#if DEBUG_IS_ON
va_list args;
va_start( args, format );
......@@ -134,8 +136,8 @@ void _Logger::debug( const std::string &format, ... )
#endif
}
void _Logger::info( const char *format, ... )
{
//------------------------------------------------------------------------------
void _Logger::info(const char *format, ...) {
#if INFO_IS_ON
va_list args;
va_start( args, format );
......@@ -144,8 +146,8 @@ void _Logger::info( const char *format, ... )
#endif
}
void _Logger::info( const std::string &format, ... )
{
//------------------------------------------------------------------------------
void _Logger::info(const std::string &format, ...) {
#if INFO_IS_ON
va_list args;
va_start( args, format );
......@@ -154,89 +156,79 @@ void _Logger::info( const std::string &format, ... )
#endif
}
void _Logger::startup( const char *format, ... )
{
//------------------------------------------------------------------------------
void _Logger::startup(const char *format, ...) {
va_list args;
va_start( args, format );
log( _ltStartup, format, args );
va_end( args );
va_start(args, format);
log(_ltStartup, format, args);
va_end(args);
}
void _Logger::startup( const std::string &format, ... )
{
//------------------------------------------------------------------------------
void _Logger::startup(const std::string &format, ...) {
va_list args;
va_start( args, format );
log( _ltStartup, format.c_str(), args );
va_end( args );
va_start(args, format);
log(_ltStartup, format.c_str(), args);
va_end(args);
}
void _Logger::warn( const char *format, ... )
{
//------------------------------------------------------------------------------
void _Logger::warn(const char *format, ...) {
va_list args;
va_start( args, format );
log( _ltWarn, format, args );
va_end( args );
va_start(args, format);
log(_ltWarn, format, args);
va_end(args);
}
void _Logger::warn( const std::string &format, ... )
{
//------------------------------------------------------------------------------
void _Logger::warn(const std::string &format, ...) {
va_list args;
va_start( args, format );
log( _ltWarn, format.c_str(), args );
va_end( args );
va_start(args, format);
log(_ltWarn, format.c_str(), args);
va_end(args);
}
void _Logger::error( const char *format, ... )
{
//------------------------------------------------------------------------------
void _Logger::error(const char *format, ...) {
va_list args;
va_start( args, format );
log( _ltError, format, args );
va_end( args );
va_start(args, format);
log(_ltError, format, args);
va_end(args);
}
void _Logger::error( const std::string &format, ... )
{
//------------------------------------------------------------------------------
void _Logger::error(const std::string &format, ...) {
va_list args;
va_start( args, format );
log( _ltError, format.c_str(), args );
va_end( args );
va_start(args, format);
log(_ltError, format.c_str(), args);
va_end(args);
}
void _Logger::log( _LogType lt, const char *format, va_list &args )
{
char buffer[ 2048 ];
vsnprintf( buffer, sizeof(buffer), format, args );
switch ( lt )
{
case _ltTrace: m_log.trace( buffer ); break;
case _ltDebug: m_log.debug( buffer ); break;
case _ltInfo: m_log.info( buffer ); break;
case _ltStartup: m_log.warn( buffer ); break;
case _ltWarn: m_log.error( buffer ); break;
case _ltError: m_log.critical( buffer ); break;
//------------------------------------------------------------------------------
void _Logger::log(_LogType lt, const char *format, va_list &args) {
char buffer[2048];
vsnprintf(buffer, sizeof(buffer), format, args);
switch (lt) {
case _ltTrace:
m_log.trace(buffer);
break;
case _ltDebug:
m_log.debug(buffer);
break;
case _ltInfo:
m_log.info(buffer);
break;
case _ltStartup:
m_log.warn(buffer);
break;
case _ltWarn:
m_log.error(buffer);
break;
case _ltError:
m_log.critical(buffer);
break;
}
}
......@@ -37,17 +37,21 @@
#define SPDLOG_ENABLE_SYSLOG
#include "spdlog/spdlog.h"
class LoggerException : public std::runtime_error
{
public:
explicit LoggerException(const char *m) : std::runtime_error(m) {}
explicit LoggerException(const std::string &m) : std::runtime_error(m) {}
class LoggerException : public std::runtime_error {
public:
explicit LoggerException(const char *m)
:
std::runtime_error(m) {
}
explicit LoggerException(const std::string &m)
:
std::runtime_error(m) {
}
};
class _Logger
{
public:
_Logger(const char * category, std::vector<spdlog::sink_ptr> &sinks, const char *pattern);
class _Logger {
public:
_Logger(const char *category, std::vector<spdlog::sink_ptr> &sinks, const char *pattern);
void trace(const char *format, ...);
void trace(const std::string &format, ...);
......@@ -62,10 +66,9 @@ public:
void error(const char *format, ...);
void error(const std::string &format, ...);
private:
private:
_Logger();
enum _LogType
{
enum _LogType {
_ltTrace,
_ltDebug,
_ltInfo,
......@@ -78,35 +81,74 @@ private:
spdlog::logger m_log;
};
class Logger
{
public:
static void init(const char *app, const bool log_stdout, const bool log_rot_file){singleton()._init(app, log_stdout, log_rot_file);}
static void init(const std::string &app, const bool log_stdout, const bool log_rot_file){init(app.c_str(), log_stdout, log_rot_file);}
static _Logger &async_cmd(){return *singleton().m_async_cmd;}
static _Logger &amf_app(){return *singleton().m_amf_app;}
static _Logger &config(){return *singleton().m_config;}
static _Logger &system(){return *singleton().m_system;}
static _Logger &sctp(){return *singleton().m_sctp;}
static _Logger &nas_mm(){return *singleton().m_nas_mm;}
static _Logger &ngap(){return *singleton().m_ngap;}
static _Logger &itti(){return *singleton().m_itti;}
static _Logger &amf_n2(){return *singleton().m_amf_n2;}
static _Logger &task_amf_n2(){return *singleton().m_task_amf_n2;}
static _Logger &amf_n1(){return *singleton().m_amf_n1;}
static _Logger &task_amf_n1(){return *singleton().m_task_amf_n1;}
static _Logger &amf_n11(){return *singleton().m_amf_n11;}
static _Logger &task_amf_n11(){return *singleton().m_task_amf_n11;}
static _Logger &amf_server(){return *singleton().m_amf_server;}
private:
class Logger {
public:
static void init(const char *app, const bool log_stdout, const bool log_rot_file) {
singleton()._init(app, log_stdout, log_rot_file);
}
static void init(const std::string &app, const bool log_stdout, const bool log_rot_file) {
init(app.c_str(), log_stdout, log_rot_file);
}
static _Logger& async_cmd() {
return *singleton().m_async_cmd;
}
static _Logger& amf_app() {
return *singleton().m_amf_app;
}
static _Logger& config() {
return *singleton().m_config;
}
static _Logger& system() {
return *singleton().m_system;
}
static _Logger& sctp() {
return *singleton().m_sctp;
}
static _Logger& nas_mm() {
return *singleton().m_nas_mm;
}
static _Logger& ngap() {
return *singleton().m_ngap;
}
static _Logger& itti() {
return *singleton().m_itti;
}
static _Logger& amf_n2() {
return *singleton().m_amf_n2;
}
static _Logger& task_amf_n2() {
return *singleton().m_task_amf_n2;
}
static _Logger& amf_n1() {
return *singleton().m_amf_n1;
}
static _Logger& task_amf_n1() {
return *singleton().m_task_amf_n1;
}
static _Logger& amf_n11() {
return *singleton().m_amf_n11;
}
static _Logger& task_amf_n11() {
return *singleton().m_task_amf_n11;
}
static _Logger& amf_server() {
return *singleton().m_amf_server;
}
private:
static Logger *m_singleton;
static Logger &singleton(){if(!m_singleton) m_singleton = new Logger(); return *m_singleton;}
static Logger& singleton() {
if (!m_singleton)
m_singleton = new Logger();
return *m_singleton;
}
Logger(){}
~Logger(){}
Logger() {
}
~Logger() {
}
void _init(const char *app, const bool log_stdout, const bool log_rot_file);
......@@ -134,8 +176,3 @@ private:
#endif
......@@ -28,4 +28,3 @@
#include "gNB_context.hpp"
......@@ -34,23 +34,23 @@
#include <vector>
#include "sctp_server.hpp"
#include "NgapIEsStruct.hpp"
extern "C"{
#include "Ngap_PagingDRX.h"
#include "bstrlib.h"
extern "C" {
#include "Ngap_PagingDRX.h"
#include "bstrlib.h"
}
using namespace sctp;
using namespace std;
using namespace ngap;
enum amf_ng_gnb_state_s{
enum amf_ng_gnb_state_s {
NGAP_INIT,
NGAP_RESETING,
NGAP_READY,
NGAP_SHUTDOWN
};
class gnb_context{
public:
class gnb_context {
public:
enum amf_ng_gnb_state_s ng_state;
string gnb_name;
......
......@@ -28,7 +28,8 @@
#include "nas_context.hpp"
nas_context::nas_context(){
//------------------------------------------------------------------------------
nas_context::nas_context() {
security_ctx = NULL;
is_imsi_present = false;
is_stacs_available = false;
......@@ -43,4 +44,6 @@ nas_context::nas_context(){
auts = NULL;
}
nas_context::~nas_context(){}
//------------------------------------------------------------------------------
nas_context::~nas_context() {
}
......@@ -36,21 +36,21 @@
#include "nas_security_context.hpp"
#include "struct.hpp"
class nas_context{
public:
class nas_context {
public:
nas_context();
~nas_context();
public:
public:
bool ctx_avaliability_ind;
bool is_stacs_available;
long amf_ue_ngap_id;
uint32_t ran_ue_ngap_id;
string nas_status;
/************ parameters from Registration request *************/
uint8_t registration_type:3;
/************ parameters from Registration request *************/
uint8_t registration_type :3;
bool follow_on_req_pending_ind;
uint8_t ngKsi:4;
uint8_t ngKsi :4;
//mobility identity: imsi, supi, 5g-guti, etc
std::string imsi;
uint8_t mmCapability;
......@@ -59,7 +59,7 @@ public:
std::vector<nas::SNSSAI_t> requestedNssai;
std::string serving_network;
bstring auts;
/************ NAS EP(s) ****************/
/************ NAS EP(s) ****************/
bool is_specific_procedure_for_registration_running;
bool is_specific_procedure_for_deregistration_running;
bool is_specific_procedure_for_eCell_inactivity_running;
......@@ -67,38 +67,25 @@ public:
bool is_common_procedure_for_identification_running;
bool is_common_procedure_for_security_mode_control_running;
bool is_common_procedure_for_nas_transport_running;
/************ security related ***********/
/************ security related ***********/
#define MAX_5GS_AUTH_VECTORS 1
auc_vector_t _vector[MAX_5GS_AUTH_VECTORS];/* 5GS authentication vector */
_5G_HE_AV_t _5g_he_av[MAX_5GS_AUTH_VECTORS];//generated by UDM
_5G_AV_t _5g_av[MAX_5GS_AUTH_VECTORS];//generated by ausf
_5G_HE_AV_t _5g_he_av[MAX_5GS_AUTH_VECTORS]; //generated by UDM
_5G_AV_t _5g_av[MAX_5GS_AUTH_VECTORS]; //generated by ausf
uint8_t kamf[MAX_5GS_AUTH_VECTORS][32];
security_context_t _security;
nas_secu_ctx *security_ctx;
bool is_current_security_avaliable;
bool is_current_security_available;
int registration_attempt_counter;//used to limit the subsequently reject registration attempts(clause 5.5.1.2.7/5.5.1.3.7, 3gpp ts24.501)
/**************** parameters present? ****************/
int registration_attempt_counter; //used to limit the subsequently reject registration attempts(clause 5.5.1.2.7/5.5.1.3.7, 3gpp ts24.501)
/**************** parameters present? ****************/
bool is_imsi_present;
bool is_5g_guti_present;
bool is_auth_vectors_present;
};
#endif
......@@ -46,7 +46,7 @@ typedef enum {
/*
Internal data used for security mode control procedure
*/
*/
typedef struct {
unsigned int ue_id; /* UE identifier */
#define SECURITY_COUNTER_MAX 5
......@@ -77,27 +77,26 @@ typedef struct {
* to the ongoing EMM procedure */
} security_data_t;
typedef uint8_t ngksi_t;
typedef struct{
uint32_t spare:8;
uint32_t overflow:16;
uint32_t seq_num:8;
}count_t;
typedef struct {
uint32_t spare :8;
uint32_t overflow :16;
uint32_t seq_num :8;
} count_t;
typedef struct{
typedef struct {
uint8_t _5gs_encryption;
uint8_t _5gs_integrity;
}capability_t;
} capability_t;
typedef struct{
uint8_t encryption:4;
uint8_t integrity:4;
}selected_algs;
typedef struct {
uint8_t encryption :4;
uint8_t integrity :4;
} selected_algs;
class nas_secu_ctx{
public:
class nas_secu_ctx {
public:
int vector_pointer;
nas_sc_type_t sc_type;
ngksi_t ngksi;
......
......@@ -28,8 +28,11 @@
#include "pdu_session_context.hpp"
pdu_session_context::pdu_session_context(){
//------------------------------------------------------------------------------
pdu_session_context::pdu_session_context() {
smf_avaliable = false;
}
pdu_session_context::~pdu_session_context(){}
//------------------------------------------------------------------------------
pdu_session_context::~pdu_session_context() {
}
......@@ -33,18 +33,18 @@
#include "bstrlib.h"
using namespace std;
class pdu_session_context{
public:
class pdu_session_context {
public:
pdu_session_context();
~pdu_session_context();
public:
public:
uint32_t ran_ue_ngap_id;
long amf_ue_ngap_id;
uint8_t req_type;
uint8_t pdu_session_id;
bstring n2sm;
string dnn;
string remote_smf_addr[0];//"192.168.12.10:8080"
string remote_smf_addr[0]; //"192.168.12.10:8080"
bool smf_avaliable;
};
#endif
......@@ -29,7 +29,6 @@
#ifndef _SECURITY_DEF_H_
#define _SECURITY_DEF_H_
#define AUTH_SQN_INDEX 0
#define AUTH_AMF_INDEX (AUTH_SQN_INDEX + AUTH_SQN_SIZE)
#define AUTH_MAC_INDEX (AUTH_AMF_INDEX + AUTH_AMF_SIZE)
......@@ -84,23 +83,25 @@ typedef struct security_context_s {
uint8_t knas_enc[AUTH_KNAS_ENC_SIZE];/* NAS cyphering key */
uint8_t knas_int[AUTH_KNAS_INT_SIZE];/* NAS integrity key */
struct count_s{
uint32_t spare:8;
uint32_t overflow:16;
uint32_t seq_num:8;
struct count_s {
uint32_t spare :8;
uint32_t overflow :16;
uint32_t seq_num :8;
} dl_count, ul_count; /* Downlink and uplink count parameters */
struct {
uint8_t eps_encryption; /* algorithm used for ciphering */
uint8_t eps_integrity; /* algorithm used for integrity protection */
uint8_t umts_encryption; /* algorithm used for ciphering */
uint8_t umts_integrity; /* algorithm used for integrity protection */
uint8_t gprs_encryption; /* algorithm used for ciphering */
bool umts_present:1;
bool gprs_present:1;
bool umts_present :1;
bool gprs_present :1;
} capability; /* UE network capability */
struct {
uint8_t encryption:4; /* algorithm used for ciphering */
uint8_t integrity:4; /* algorithm used for integrity protection */
uint8_t encryption :4; /* algorithm used for ciphering */
uint8_t integrity :4; /* algorithm used for integrity protection */
} selected_algorithms; /* MME selected algorithms */
// Requirement MME24.301R10_4.4.4.3_2 (DETACH REQUEST (if sent before security has been activated);)
......
......@@ -34,16 +34,16 @@
#include "NgapIEsStruct.hpp"
#include <shared_mutex>
extern "C"{
#include "Ngap_RRCEstablishmentCause.h"
extern "C" {
#include "Ngap_RRCEstablishmentCause.h"
}
using namespace ngap;
class ue_context{
public:
uint32_t ran_ue_ngap_id;//32bits
long amf_ue_ngap_id:40;//40bits
class ue_context {
public:
uint32_t ran_ue_ngap_id; //32bits
long amf_ue_ngap_id :40; //40bits
e_Ngap_RRCEstablishmentCause rrc_estb_cause;
bool isUeContextRequest;
......
......@@ -35,23 +35,23 @@
#include <shared_mutex>
using namespace sctp;
typedef enum{
typedef enum {
NGAP_UE_INVALID_STATE,
NGAP_UE_WAITING_CSR,//Context Setup Response(CSR)
NGAP_UE_WAITING_CSR, //Context Setup Response(CSR)
NGAP_UE_HANDOVER,
NGAP_UE_CONNECTED,
NGAP_UE_WAITING_CRR
}ng_ue_state_t;
} ng_ue_state_t;
class ue_ngap_context{
public:
uint32_t ran_ue_ngap_id;//32bits
long amf_ue_ngap_id:40;//40bits
class ue_ngap_context {
public:
uint32_t ran_ue_ngap_id; //32bits
long amf_ue_ngap_id :40; //40bits
sctp_stream_id_t sctp_stream_recv;// used to decide which ue in gNB
sctp_stream_id_t sctp_stream_send;// used to decide which ue in gNB
sctp_stream_id_t sctp_stream_recv; // used to decide which ue in gNB
sctp_stream_id_t sctp_stream_send; // used to decide which ue in gNB
sctp_assoc_id_t gnb_assoc_id;//to find which gnb this UE belongs to
sctp_assoc_id_t gnb_assoc_id; //to find which gnb this UE belongs to
bool ueContextRequest;
uint32_t s_tmsi_5g;
......
......@@ -23,7 +23,7 @@
\author Lionel GAUTHIER
\date 2018
\email: lionel.gauthier@eurecom.fr
*/
*/
#include "logger.hpp"
#include "itti.hpp"
#include "common_defs.h"
......@@ -39,14 +39,14 @@ extern itti_mw *itti_inst;
static itti_timer null_timer(ITTI_INVALID_TIMER_ID, TASK_NONE, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0);
//------------------------------------------------------------------------------
void itti_mw::timer_manager_task(const util::thread_sched_params& sched_params)
{
void itti_mw::timer_manager_task(const util::thread_sched_params &sched_params) {
Logger::itti().info("Starting timer_manager_task");
sched_params.apply(TASK_ITTI_TIMER, Logger::itti());
while (true) {
if (itti_inst->terminate) return;
if (itti_inst->terminate)
return;
{
std::unique_lock<std::mutex> lx(itti_inst->m_timers);
std::unique_lock < std::mutex > lx(itti_inst->m_timers);
while (itti_inst->timers.empty()) {
itti_inst->c_timers.wait(lx);
}
......@@ -57,14 +57,14 @@ void itti_mw::timer_manager_task(const util::thread_sched_params& sched_params)
// check time-out
if (itti_inst->current_timer.time_out > std::chrono::system_clock::now()) {
std::unique_lock<std::mutex> lto(itti_inst->m_timeout);
std::unique_lock < std::mutex > lto(itti_inst->m_timeout);
auto diff = itti_inst->current_timer.time_out - std::chrono::system_clock::now();
auto rc = itti_inst->c_timeout.wait_for( lto, diff);
auto rc = itti_inst->c_timeout.wait_for(lto, diff);
lto.unlock();
if ( std::cv_status::timeout == rc) {
if (std::cv_status::timeout == rc) {
// signal time-out
itti_msg_timeout mto(TASK_ITTI_TIMER, itti_inst->current_timer.task_id, itti_inst->current_timer.id, itti_inst->current_timer.arg1_user, itti_inst->current_timer.arg2_user);
std::shared_ptr<itti_msg_timeout> msgsh = std::make_shared<itti_msg_timeout>(mto);
std::shared_ptr<itti_msg_timeout> msgsh = std::make_shared < itti_msg_timeout > (mto);
int ret = itti_inst->send_msg(msgsh);
} else {
// other timer required ?
......@@ -79,15 +79,25 @@ void itti_mw::timer_manager_task(const util::thread_sched_params& sched_params)
} else {
// signal time-out
itti_msg_timeout mto(TASK_ITTI_TIMER, itti_inst->current_timer.task_id, itti_inst->current_timer.id, itti_inst->current_timer.arg1_user, itti_inst->current_timer.arg2_user);
std::shared_ptr<itti_msg_timeout> msgsh = std::make_shared<itti_msg_timeout>(mto);
std::shared_ptr<itti_msg_timeout> msgsh = std::make_shared < itti_msg_timeout > (mto);
itti_inst->send_msg(msgsh);
}
}
}
}
//------------------------------------------------------------------------------
itti_mw::itti_mw() : timer_id(0), msg_number(0), created_tasks(0), ready_tasks(0), m_timers(), current_timer(null_timer), m_timeout(), m_timer_id(), terminate(false) {
std::fill(itti_task_ctxts, itti_task_ctxts+TASK_MAX, nullptr );
itti_mw::itti_mw()
:
timer_id(0),
msg_number(0),
created_tasks(0),
ready_tasks(0),
m_timers(),
current_timer(null_timer),
m_timeout(),
m_timer_id(),
terminate(false) {
std::fill(itti_task_ctxts, itti_task_ctxts + TASK_MAX, nullptr);
}
//------------------------------------------------------------------------------
......@@ -95,7 +105,7 @@ itti_mw::~itti_mw() {
std::cout << "~itti()" << std::endl;
timer_thread.detach();
// wake up thread timer if necessary
std::unique_lock<std::mutex> l2(m_timeout);
std::unique_lock < std::mutex > l2(m_timeout);
c_timeout.notify_one();
for (int t = TASK_FIRST; t < TASK_MAX; t++) {
......@@ -107,44 +117,41 @@ itti_mw::~itti_mw() {
}
//------------------------------------------------------------------------------
void itti_mw::start(const util::thread_sched_params& sched_params) {
Logger::itti().startup( "Starting..." );
void itti_mw::start(const util::thread_sched_params &sched_params) {
Logger::itti().startup("Starting...");
timer_thread = std::thread(timer_manager_task, sched_params);
Logger::itti().startup( "Started" );
Logger::itti().startup("Started");
}
//------------------------------------------------------------------------------
timer_id_t itti_mw::increment_timer_id () {
timer_id_t itti_mw::increment_timer_id() {
return ++timer_id;
}
//------------------------------------------------------------------------------
unsigned int itti_mw::increment_message_number () {
unsigned int itti_mw::increment_message_number() {
return __sync_fetch_and_add(&msg_number, 1);
}
//------------------------------------------------------------------------------
int itti_mw::create_task (const task_id_t task_id,
void (*start_routine) (void *),
void *args_p)
{
int itti_mw::create_task(const task_id_t task_id, void (*start_routine)(void*), void *args_p) {
if (nullptr == start_routine) {
Logger::itti().error("Null start routine for task %d", task_id);
return RETURNerror;
return RETURNerror ;
}
if ((TASK_FIRST <= task_id) && (TASK_MAX > task_id)) {
if (itti_task_ctxts[task_id] == nullptr) {
itti_task_ctxts[task_id] = new itti_task_ctxt(task_id);
{
std::unique_lock<std::mutex> lk(itti_task_ctxts[task_id]->m_state);
std::unique_lock < std::mutex > lk(itti_task_ctxts[task_id]->m_state);
if (itti_task_ctxts[task_id]->task_state == TASK_STATE_NOT_CONFIGURED) {
itti_task_ctxts[task_id]->task_state = TASK_STATE_STARTING;
}
created_tasks++;
lk.unlock();
}
itti_task_ctxts[task_id]->thread = std::thread(start_routine,args_p);
itti_task_ctxts[task_id]->thread = std::thread(start_routine, args_p);
while ((itti_task_ctxts[task_id]->task_state != TASK_STATE_READY) && (itti_task_ctxts[task_id]->task_state != TASK_STATE_ENDED))
usleep (1000);
usleep(1000);
return 0;
} else {
Logger::itti().error("Try to start an already started task %d", task_id);
......@@ -152,25 +159,24 @@ int itti_mw::create_task (const task_id_t task_id,
} else {
Logger::itti().error("Bad task id %d", task_id);
}
return RETURNerror;
return RETURNerror ;
}
//------------------------------------------------------------------------------
int itti_mw::notify_task_ready(const task_id_t task_id)
{
int itti_mw::notify_task_ready(const task_id_t task_id) {
if (itti_task_ctxts[task_id]) {
itti_task_ctxts[task_id]->m_state.lock();
if (itti_task_ctxts[task_id]->task_state == TASK_STATE_STARTING) {
itti_task_ctxts[task_id]->task_state = TASK_STATE_READY;
itti_task_ctxts[task_id]->m_state.unlock();
return RETURNok;
return RETURNok ;
}
itti_task_ctxts[task_id]->m_state.unlock();
Logger::itti().error("Notify task ready, bad state %d", itti_task_ctxts[task_id]->task_state);
} else {
Logger::itti().error("Notify task ready, task not starting %d", task_id);
}
return RETURNerror;
return RETURNerror ;
}
//------------------------------------------------------------------------------
......@@ -180,24 +186,22 @@ int itti_mw::send_msg(std::shared_ptr<itti_msg> message) {
if (itti_task_ctxts[message->destination]) {
if (itti_task_ctxts[message->destination]->task_state == TASK_STATE_READY) {
std::unique_lock<std::mutex> l(itti_task_ctxts[message->destination]->m_queue);
std::unique_lock < std::mutex > l(itti_task_ctxts[message->destination]->m_queue);
//res =
itti_task_ctxts[message->destination]->msg_queue.push(message);
itti_task_ctxts[message->destination]->c_queue.notify_one();
return RETURNok;
return RETURNok ;
} else if (itti_task_ctxts[message->destination]->task_state == TASK_STATE_ENDED) {
Logger::itti().warn("Unicast message number %lu can not be sent from %d to %d, ended destination task!",
message->msg_num, message->origin, message->destination);
return RETURNerror;
Logger::itti().warn("Unicast message number %lu can not be sent from %d to %d, ended destination task!", message->msg_num, message->origin, message->destination);
return RETURNerror ;
}
} else {
Logger::itti().warn("Unicast message number %lu can not be sent from %d to %d, not started destination task!",
message->msg_num, message->origin, message->destination);
Logger::itti().warn("Unicast message number %lu can not be sent from %d to %d, not started destination task!", message->msg_num, message->origin, message->destination);
}
} else if (message->destination == TASK_ALL) {
return send_broadcast_msg(message);
}
return RETURNerror;
return RETURNerror ;
}
//------------------------------------------------------------------------------
......@@ -207,21 +211,19 @@ int itti_mw::send_broadcast_msg(std::shared_ptr<itti_msg> message) {
for (int t = TASK_FIRST; t < TASK_MAX; t++) {
if (itti_task_ctxts[t]) {
if (itti_task_ctxts[t]->task_state == TASK_STATE_READY) {
std::unique_lock<std::mutex> l(itti_task_ctxts[t]->m_queue);
std::unique_lock < std::mutex > l(itti_task_ctxts[t]->m_queue);
itti_task_ctxts[t]->msg_queue.push(message);
itti_task_ctxts[t]->c_queue.notify_one();
} else if (itti_task_ctxts[t]->task_state == TASK_STATE_ENDED) {
Logger::itti().warn("Broadcast message number %lu can not be sent from %d to %d, ended destination task!",
message->msg_num, message->origin, t);
Logger::itti().warn("Broadcast message number %lu can not be sent from %d to %d, ended destination task!", message->msg_num, message->origin, t);
} else {
Logger::itti().warn("Broadcast message number %lu can not be sent from %d to %d, unknown state %d !",
message->msg_num, message->origin, t, itti_task_ctxts[t]->task_state);
Logger::itti().warn("Broadcast message number %lu can not be sent from %d to %d, unknown state %d !", message->msg_num, message->origin, t, itti_task_ctxts[t]->task_state);
}
}
}
return RETURNok;
return RETURNok ;
}
return RETURNerror;
return RETURNerror ;
}
//------------------------------------------------------------------------------
......@@ -229,17 +231,16 @@ int itti_mw::send_terminate_msg(task_id_t src_task_id) {
itti_msg_terminate msg(src_task_id, TASK_ALL);
terminate = true;
std::shared_ptr<itti_msg_terminate> smsg = std::make_shared<itti_msg_terminate>(msg);
std::shared_ptr<itti_msg_terminate> smsg = std::make_shared < itti_msg_terminate > (msg);
int ret = itti_inst->send_broadcast_msg(smsg);
return ret;
}
//------------------------------------------------------------------------------
std::shared_ptr<itti_msg> itti_mw::receive_msg (task_id_t task_id)
{
std::shared_ptr<itti_msg> itti_mw::receive_msg(task_id_t task_id) {
if ((TASK_FIRST <= task_id) && (TASK_MAX > task_id)) {
if (itti_task_ctxts[task_id]) {
std::unique_lock<std::mutex> lk(itti_task_ctxts[task_id]->m_queue);
std::unique_lock < std::mutex > lk(itti_task_ctxts[task_id]->m_queue);
while (itti_task_ctxts[task_id]->msg_queue.empty()) {
itti_task_ctxts[task_id]->c_queue.wait(lk);
}
......@@ -253,11 +254,10 @@ std::shared_ptr<itti_msg> itti_mw::receive_msg (task_id_t task_id)
}
//------------------------------------------------------------------------------
std::shared_ptr<itti_msg> itti_mw::poll_msg (task_id_t task_id)
{
std::shared_ptr<itti_msg> itti_mw::poll_msg(task_id_t task_id) {
if ((TASK_FIRST <= task_id) && (TASK_MAX > task_id)) {
if (itti_task_ctxts[task_id]) {
std::lock_guard<std::mutex> lk(itti_task_ctxts[task_id]->m_queue);
std::lock_guard < std::mutex > lk(itti_task_ctxts[task_id]->m_queue);
if (!itti_task_ctxts[task_id]->msg_queue.empty()) {
std::shared_ptr<itti_msg> msg = itti_task_ctxts[task_id]->msg_queue.front();
itti_task_ctxts[task_id]->msg_queue.pop();
......@@ -269,8 +269,7 @@ std::shared_ptr<itti_msg> itti_mw::poll_msg (task_id_t task_id)
}
//------------------------------------------------------------------------------
void itti_mw::wait_tasks_end (void)
{
void itti_mw::wait_tasks_end(void) {
Logger::itti().info("Waiting ITTI tasks closed");
for (int task_idx = TASK_FIRST; task_idx < TASK_MAX; task_idx++) {
......@@ -287,52 +286,45 @@ void itti_mw::wait_tasks_end (void)
}
//------------------------------------------------------------------------------
timer_id_t itti_mw::timer_setup (
uint32_t interval_sec,
uint32_t interval_us,
task_id_t task_id,
uint64_t arg1_user,
uint64_t arg2_user)
{
timer_id_t itti_mw::timer_setup(uint32_t interval_sec, uint32_t interval_us, task_id_t task_id, uint64_t arg1_user, uint64_t arg2_user) {
// Not sending to task timer
if ((TASK_FIRST < task_id) && (TASK_MAX > task_id)) {
itti_timer t(increment_timer_id(), task_id, interval_sec, interval_us, arg1_user, arg2_user);
timer_id_t id = t.id;
std::unique_lock<std::mutex> l(m_timers);
std::unique_lock < std::mutex > l(m_timers);
timers.insert(t);
c_timers.notify_one();
// wake up thread timer if necessary
std::unique_lock<std::mutex> l2(m_timeout);
std::unique_lock < std::mutex > l2(m_timeout);
c_timeout.notify_one();
return id;
}
return ITTI_INVALID_TIMER_ID;
return ITTI_INVALID_TIMER_ID ;
}
//------------------------------------------------------------------------------
int itti_mw::timer_remove (timer_id_t timer_id)
{
std::lock_guard<std::mutex> lk(m_timers);
int itti_mw::timer_remove(timer_id_t timer_id) {
std::lock_guard < std::mutex > lk(m_timers);
if (current_timer.id == timer_id) {
//cout << "timer_remove() current_timer.id == timer_id" << endl;
current_timer = null_timer;
c_timers.notify_one();
// wake up thread timer if necessary
std::unique_lock<std::mutex> l2(m_timeout);
std::unique_lock < std::mutex > l2(m_timeout);
c_timeout.notify_one();
return RETURNok;
return RETURNok ;
} else {
std::set<itti_timer>::iterator it = itti_inst->timers.begin();
while(it != itti_inst->timers.end()) {
while (it != itti_inst->timers.end()) {
if (it->id == timer_id) {
itti_inst->timers.erase(it);
return RETURNok;
return RETURNok ;
}
++it;
}
}
Logger::itti().trace("Removing timer 0x%lx: Not found", timer_id);
return RETURNerror;
return RETURNerror ;
}
......@@ -11,25 +11,26 @@
#include "ngap_app.hpp"
#include "itti.hpp"
using namespace std;
using namespace config;
using namespace ngap;
amf_config amf_cfg;
ngap_app * ngap_inst = NULL;
ngap_app *ngap_inst = NULL;
itti_mw *itti_inst = nullptr;
void amf_ngap_app_task(void*){
//------------------------------------------------------------------------------
void amf_ngap_app_task(void*) {
const task_id_t task_id = TASK_NGAP_APP;
itti_inst->notify_task_ready(task_id);
Logger::itti().debug("task(%d) ready",TASK_NGAP_APP);
Logger::itti().debug("task(%d) ready", TASK_NGAP_APP);
}
int main(int argc, char **argv){
//------------------------------------------------------------------------------
int main(int argc, char **argv) {
srand (time(NULL));
if(!Options::parse(argc, argv)){
if (!Options::parse(argc, argv)) {
cout<<"Options::parse() failed"<<endl;
return 1;
}
......
......@@ -27,7 +27,7 @@
#include <cstring>
#include "normalizer.hh"
extern void hexStr2Byte(const char* src, unsigned char *dest, int len);
extern void hexStr2Byte(const char *src, unsigned char *dest, int len);
extern void print_buffer(const std::string app, const std::string commit, uint8_t *buf, int len);
extern void ue_gnb_simulator();
......@@ -43,11 +43,11 @@ itti_mw *itti_inst = nullptr;
amf_app *amf_app_inst = nullptr;
statistics stacs;
int main(int argc, char **argv){
//------------------------------------------------------------------------------
int main(int argc, char **argv) {
srand (time(NULL));
if(!Options::parse(argc, argv)){
if (!Options::parse(argc, argv)) {
cout<<"Options::parse() failed"<<endl;
return 1;
}
......
/*
* Copyright (c) 2017 Sprint
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
* Copyright (c) 2017 Sprint
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <iostream>
#include <stdlib.h>
......@@ -28,79 +27,88 @@ std::string Options::m_libconfigcfg;
bool Options::m_log_rot_file_log;
bool Options::m_log_stdout;
void Options::help()
{
std::cout << std::endl
<< "Usage: smf [OPTIONS]..." << std::endl
<< " -h, --help Print help and exit" << std::endl
<< " -c, --libconfigcfg filename Read the application configuration from this file." << std::endl
<< " -o, --stdoutlog Send the application logs to STDOUT fd." << std::endl
<< " -r, --rotatelog Send the application logs to local file (in current working directory)." << std::endl
;
//------------------------------------------------------------------------------
void Options::help() {
std::cout << std::endl << "Usage: smf [OPTIONS]..." << std::endl << " -h, --help Print help and exit" << std::endl << " -c, --libconfigcfg filename Read the application configuration from this file." << std::endl
<< " -o, --stdoutlog Send the application logs to STDOUT fd." << std::endl << " -r, --rotatelog Send the application logs to local file (in current working directory)." << std::endl;
}
bool Options::parse( int argc, char **argv ){
//------------------------------------------------------------------------------
bool Options::parse(int argc, char **argv) {
bool ret = true;
ret = parseInputOptions( argc, argv );
ret = parseInputOptions(argc, argv);
ret &= validateOptions();
return ret;
}
//------------------------------------------------------------------------------
bool Options::validateOptions() {
bool Options::validateOptions(){
return (
(options & libconfigcfg)
);
return ((options & libconfigcfg));
}
bool Options::parseInputOptions( int argc, char **argv )
{
//------------------------------------------------------------------------------
bool Options::parseInputOptions(int argc, char **argv) {
int c;
int option_index = 0;
bool result = true;
struct option long_options[] = {
{ "help", no_argument, NULL, 'h' },
{ "libconfigcfg", required_argument, NULL, 'f' },
{ "stdoutlog", no_argument, NULL, 'o' },
{ "rotatelog", no_argument, NULL, 'r' },
{ NULL,0,NULL,0 }
};
struct option long_options[] = { { "help", no_argument, NULL, 'h' }, { "libconfigcfg", required_argument, NULL, 'f' }, { "stdoutlog", no_argument, NULL, 'o' }, { "rotatelog", no_argument, NULL, 'r' }, { NULL, 0, NULL, 0 } };
// Loop on arguments
while (1)
{
c = getopt_long(argc, argv, "horc:", long_options, &option_index );
while (1) {
c = getopt_long(argc, argv, "horc:", long_options, &option_index);
if (c == -1)
break; // Exit from the loop.
switch (c)
{
case 'h': { help(); exit(0); break; }
case 'c': { m_libconfigcfg = optarg; options |= libconfigcfg; break; }
case 'o': { m_log_stdout = true; options |= log_stdout; break; }
case 'r': { m_log_rot_file_log = true; options |= log_rot_file_log; break; }
case '?':
{
switch ( optopt )
{
case 'c': { std::cout << "Option -l (libconfig config) requires an argument" << std::endl; break; }
case 'o': { std::cout << "Option -o do not requires an argument, can be also set with option -r." << std::endl; break; }
case 'r': { std::cout << "Option -r do not requires an argument, can be also set with option -o." << std::endl; break; }
default: { std::cout << "Unrecognized option [" << c << "]" << std::endl; break; }
switch (c) {
case 'h': {
help();
exit(0);
break;
}
case 'c': {
m_libconfigcfg = optarg;
options |= libconfigcfg;
break;
}
case 'o': {
m_log_stdout = true;
options |= log_stdout;
break;
}
case 'r': {
m_log_rot_file_log = true;
options |= log_rot_file_log;
break;
}
case '?': {
switch (optopt) {
case 'c': {
std::cout << "Option -l (libconfig config) requires an argument" << std::endl;
break;
}
case 'o': {
std::cout << "Option -o do not requires an argument, can be also set with option -r." << std::endl;
break;
}
case 'r': {
std::cout << "Option -r do not requires an argument, can be also set with option -o." << std::endl;
break;
}
default: {
std::cout << "Unrecognized option [" << c << "]" << std::endl;
break;
}
}
result = false;
break;
}
default:
{
default: {
std::cout << "Unrecognized option [" << c << "]" << std::endl;
result = false;
}
......
......@@ -20,28 +20,28 @@ void AMFApiServer::init(size_t thr) {
Logger::amf_server().debug("Initiate AMF server endpoints done!");
}
void AMFApiServer::start(){
if(m_individualSubscriptionDocumentApiImpl != nullptr)
void AMFApiServer::start() {
if (m_individualSubscriptionDocumentApiImpl != nullptr)
Logger::amf_server().debug("AMF handler for IndividualSubscriptionDocumentApiImpl");
if(m_individualUeContextDocumentApiImpl != nullptr)
if (m_individualUeContextDocumentApiImpl != nullptr)
Logger::amf_server().debug("AMF handler for IndividualUeContextDocumentApiImpl");
if(m_n1N2IndividualSubscriptionDocumentApiImpl != nullptr)
if (m_n1N2IndividualSubscriptionDocumentApiImpl != nullptr)
Logger::amf_server().debug("AMF handler for N1N2IndividualSubscriptionDocumentApiImpl");
if(m_n1N2MessageCollectionDocumentApiImpl != nullptr)
if (m_n1N2MessageCollectionDocumentApiImpl != nullptr)
Logger::amf_server().debug("AMF handler for N1N2MessageCollectionDocumentApiImpl");
if(m_n1N2SubscriptionsCollectionForIndividualUEContextsDocumentApiImpl != nullptr)
if (m_n1N2SubscriptionsCollectionForIndividualUEContextsDocumentApiImpl != nullptr)
Logger::amf_server().debug("AMF handler for N1N2SubscriptionsCollectionForIndividualUEContextsDocumentApiImpl");
if(m_nonUEN2MessageNotificationIndividualSubscriptionDocumentApiImpl != nullptr)
if (m_nonUEN2MessageNotificationIndividualSubscriptionDocumentApiImpl != nullptr)
Logger::amf_server().debug("AMF handler for NonUEN2MessageNotificationIndividualSubscriptionDocumentApiImpl");
if(m_nonUEN2MessagesCollectionDocumentApiImpl != nullptr)
if (m_nonUEN2MessagesCollectionDocumentApiImpl != nullptr)
Logger::amf_server().debug("AMF handler for NonUEN2MessagesCollectionDocumentApiImpl");
if(m_nonUEN2MessagesSubscriptionsCollectionDocumentApiImpl != nullptr)
if (m_nonUEN2MessagesSubscriptionsCollectionDocumentApiImpl != nullptr)
Logger::amf_server().debug("AMF handler for NonUEN2MessagesSubscriptionsCollectionDocumentApiImpl");
if(m_subscriptionsCollectionDocumentApiImpl != nullptr)
if (m_subscriptionsCollectionDocumentApiImpl != nullptr)
Logger::amf_server().debug("AMF handler for SubscriptionsCollectionDocumentApiImpl");
m_httpEndpoint->setHandler(m_router->handler());
m_httpEndpoint->serve();
}
void AMFApiServer::shutdown(){
void AMFApiServer::shutdown() {
m_httpEndpoint->shutdown();
}
......@@ -24,26 +24,28 @@
using namespace oai::amf::api;
class AMFApiServer{
public:
AMFApiServer(Pistache::Address address, amf_application::amf_app *amf_app_inst) : m_httpEndpoint(std::make_shared<Pistache::Http::Endpoint>(address)){
class AMFApiServer {
public:
AMFApiServer(Pistache::Address address, amf_application::amf_app *amf_app_inst)
:
m_httpEndpoint(std::make_shared < Pistache::Http::Endpoint > (address)) {
m_router = std::make_shared<Pistache::Rest::Router>();
m_individualSubscriptionDocumentApiImpl = std::make_shared<IndividualSubscriptionDocumentApiImpl> (m_router, amf_app_inst);
m_individualUeContextDocumentApiImpl = std::make_shared<IndividualUeContextDocumentApiImpl>(m_router, amf_app_inst);
m_n1N2IndividualSubscriptionDocumentApiImpl = std::make_shared<N1N2IndividualSubscriptionDocumentApiImpl>(m_router, amf_app_inst);
m_n1N2MessageCollectionDocumentApiImpl = std::make_shared<N1N2MessageCollectionDocumentApiImpl>(m_router, amf_app_inst);
m_n1N2SubscriptionsCollectionForIndividualUEContextsDocumentApiImpl = std::make_shared<N1N2SubscriptionsCollectionForIndividualUEContextsDocumentApiImpl>(m_router, amf_app_inst);
m_nonUEN2MessageNotificationIndividualSubscriptionDocumentApiImpl= std::make_shared<NonUEN2MessageNotificationIndividualSubscriptionDocumentApiImpl>(m_router, amf_app_inst);
m_nonUEN2MessagesCollectionDocumentApiImpl = std::make_shared<NonUEN2MessagesCollectionDocumentApiImpl>(m_router, amf_app_inst);
m_nonUEN2MessagesSubscriptionsCollectionDocumentApiImpl = std::make_shared<NonUEN2MessagesSubscriptionsCollectionDocumentApiImpl>(m_router, amf_app_inst);
m_subscriptionsCollectionDocumentApiImpl = std::make_shared<SubscriptionsCollectionDocumentApiImpl>(m_router, amf_app_inst);
m_individualSubscriptionDocumentApiImpl = std::make_shared < IndividualSubscriptionDocumentApiImpl > (m_router, amf_app_inst);
m_individualUeContextDocumentApiImpl = std::make_shared < IndividualUeContextDocumentApiImpl > (m_router, amf_app_inst);
m_n1N2IndividualSubscriptionDocumentApiImpl = std::make_shared < N1N2IndividualSubscriptionDocumentApiImpl > (m_router, amf_app_inst);
m_n1N2MessageCollectionDocumentApiImpl = std::make_shared < N1N2MessageCollectionDocumentApiImpl > (m_router, amf_app_inst);
m_n1N2SubscriptionsCollectionForIndividualUEContextsDocumentApiImpl = std::make_shared < N1N2SubscriptionsCollectionForIndividualUEContextsDocumentApiImpl > (m_router, amf_app_inst);
m_nonUEN2MessageNotificationIndividualSubscriptionDocumentApiImpl = std::make_shared < NonUEN2MessageNotificationIndividualSubscriptionDocumentApiImpl > (m_router, amf_app_inst);
m_nonUEN2MessagesCollectionDocumentApiImpl = std::make_shared < NonUEN2MessagesCollectionDocumentApiImpl > (m_router, amf_app_inst);
m_nonUEN2MessagesSubscriptionsCollectionDocumentApiImpl = std::make_shared < NonUEN2MessagesSubscriptionsCollectionDocumentApiImpl > (m_router, amf_app_inst);
m_subscriptionsCollectionDocumentApiImpl = std::make_shared < SubscriptionsCollectionDocumentApiImpl > (m_router, amf_app_inst);
}
void init(size_t thr = 1);
void start();
void shutdown();
private:
private:
std::shared_ptr<Pistache::Http::Endpoint> m_httpEndpoint;
std::shared_ptr<Pistache::Rest::Router> m_router;
std::shared_ptr<IndividualSubscriptionDocumentApiImpl> m_individualSubscriptionDocumentApiImpl;
......
......@@ -26,100 +26,113 @@
\email: contact@openairinterface.org
*/
#include "sctp_server.hpp"
#include "logger.hpp"
extern "C"{
#include <netinet/in.h>
#include <netinet/sctp.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
#include <arpa/inet.h>
extern "C" {
#include <netinet/in.h>
#include <netinet/sctp.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
#include <arpa/inet.h>
#include "bstrlib.h"
#include "bstrlib.h"
}
#include <iostream>
using namespace std;
namespace sctp{
namespace sctp {
/*
uint32_t sctp_application::getPpid(){
return ppid_;
}
*/
sctp_server::sctp_server(const char *address, const uint16_t port_num){
*/
//------------------------------------------------------------------------------
sctp_server::sctp_server(const char *address, const uint16_t port_num) {
Logger::sctp().debug("creating socket!!");
create_socket(address, port_num);
}
sctp_server::~sctp_server(){}
int sctp_server::create_socket (const char * address, const uint16_t port_num){
if ((socket_ = socket (AF_INET6, SOCK_STREAM, IPPROTO_SCTP)) < 0) {
Logger::sctp().error("socket: %s:%d",strerror(errno),errno);
}
//------------------------------------------------------------------------------
sctp_server::~sctp_server() {
}
//------------------------------------------------------------------------------
int sctp_server::create_socket(const char *address, const uint16_t port_num) {
if ((socket_ = socket(AF_INET6, SOCK_STREAM, IPPROTO_SCTP)) < 0) {
Logger::sctp().error("socket: %s:%d", strerror(errno), errno);
return -1;
}
Logger::sctp().info("Created socket(%d)",socket_);
bzero(&serverAddr_,sizeof(serverAddr_));
Logger::sctp().info("Created socket(%d)", socket_);
bzero(&serverAddr_, sizeof(serverAddr_));
serverAddr_.sin_family = AF_INET;
serverAddr_.sin_addr.s_addr = htonl(INADDR_ANY);
serverAddr_.sin_port = htons(port_num);
inet_pton(AF_INET,address,&serverAddr_.sin_addr);
if(bind(socket_,(struct sockaddr *)&serverAddr_,sizeof(serverAddr_)) != 0){
Logger::sctp().error("socket bind: %s:%d",strerror(errno),errno);
inet_pton(AF_INET, address, &serverAddr_.sin_addr);
if (bind(socket_, (struct sockaddr*) &serverAddr_, sizeof(serverAddr_)) != 0) {
Logger::sctp().error("socket bind: %s:%d", strerror(errno), errno);
}
bzero(&events_,sizeof(events_));
bzero(&events_, sizeof(events_));
events_.sctp_data_io_event = 1;
events_.sctp_shutdown_event = 1;
events_.sctp_association_event = 1;
setsockopt (socket_, IPPROTO_SCTP, SCTP_EVENTS, &events_, sizeof (struct sctp_event_subscribe));
listen(socket_,5);
}
void sctp_server::start_receive(sctp_application *app){
setsockopt(socket_, IPPROTO_SCTP, SCTP_EVENTS, &events_, sizeof(struct sctp_event_subscribe));
listen(socket_, 5);
}
//------------------------------------------------------------------------------
void sctp_server::start_receive(sctp_application *app) {
app_ = app;
pthread_create(&thread_, NULL, sctp_receiver_thread, (void *)this);
}
void *sctp_server::sctp_receiver_thread(void * arg){
sctp_server * ptr = (sctp_server*)arg;
pthread_create(&thread_, NULL, sctp_receiver_thread, (void*) this);
}
//------------------------------------------------------------------------------
void* sctp_server::sctp_receiver_thread(void *arg) {
sctp_server *ptr = (sctp_server*) arg;
Logger::sctp().info("Create pthread to receive sctp message");
int fdmax;
int clientsock;
fd_set master;
fd_set read_fds;
if(arg == NULL) pthread_exit(NULL);
FD_ZERO (&master);
FD_ZERO (&read_fds);
FD_SET (ptr->getSocket(), &master);
if (arg == NULL)
pthread_exit (NULL);
FD_ZERO(&master);
FD_ZERO(&read_fds);
FD_SET(ptr->getSocket(), &master);
fdmax = ptr->getSocket();
while(1){
memcpy (&read_fds, &master, sizeof (master));
if (select (fdmax + 1, &read_fds, NULL, NULL, NULL) == -1) {
Logger::sctp().error("[socket(%d)] Select() error: %s:%d",ptr->getSocket(),strerror(errno),errno);
while (1) {
memcpy(&read_fds, &master, sizeof(master));
if (select(fdmax + 1, &read_fds, NULL, NULL, NULL) == -1) {
Logger::sctp().error("[socket(%d)] Select() error: %s:%d", ptr->getSocket(), strerror(errno), errno);
pthread_exit (NULL);
}
for(int i=0;i<=fdmax;i++){
if (FD_ISSET (i, &read_fds)) {
for (int i = 0; i <= fdmax; i++) {
if (FD_ISSET(i, &read_fds)) {
if (i == ptr->getSocket()) {
if ((clientsock = accept (ptr->getSocket(), NULL, NULL)) < 0) {
Logger::sctp().error("[socket(%d)] accept() error: %s:%d",ptr->getSocket(),strerror(errno),errno);
if ((clientsock = accept(ptr->getSocket(), NULL, NULL)) < 0) {
Logger::sctp().error("[socket(%d)] accept() error: %s:%d", ptr->getSocket(), strerror(errno), errno);
pthread_exit (NULL);
}else{
FD_SET (clientsock, &master);
if(clientsock > fdmax) fdmax = clientsock;
}
}else{
int ret = ptr->sctp_read_from_socket (i, ptr->app_->getPpid());
if(ret == SCTP_RC_DISCONNECT){
FD_CLR (i, &master);
} else {
FD_SET(clientsock, &master);
if (clientsock > fdmax)
fdmax = clientsock;
}
} else {
int ret = ptr->sctp_read_from_socket(i, ptr->app_->getPpid());
if (ret == SCTP_RC_DISCONNECT) {
FD_CLR(i, &master);
if (i == fdmax) {
while (FD_ISSET (fdmax, &master) == false) fdmax -= 1;
while (FD_ISSET(fdmax, &master) == false)
fdmax -= 1;
}
}
......@@ -128,75 +141,85 @@ namespace sctp{
}
}
return NULL;
}
int sctp_server::getSocket(){
}
//------------------------------------------------------------------------------
int sctp_server::getSocket() {
return socket_;
}
int sctp_server::sctp_read_from_socket(int sd, uint32_t ppid){
}
//------------------------------------------------------------------------------
int sctp_server::sctp_read_from_socket(int sd, uint32_t ppid) {
int flags = 0;
socklen_t from_len = 0;
struct sctp_sndrcvinfo sinfo = {0};
struct sockaddr_in6 addr = {0};
struct sctp_sndrcvinfo sinfo = { 0 };
struct sockaddr_in6 addr = { 0 };
uint8_t buffer[SCTP_RECV_BUFFER_SIZE];
if(sd < 0) return -1;
memset ((void *)&addr, 0, sizeof (struct sockaddr_in6));
from_len = (socklen_t) sizeof (struct sockaddr_in6);
memset ((void *)&sinfo, 0, sizeof (struct sctp_sndrcvinfo));
int n = sctp_recvmsg (sd, (void *)buffer, SCTP_RECV_BUFFER_SIZE, (struct sockaddr *)&addr, &from_len, &sinfo, &flags);
if(n < 0){
Logger::sctp().error("sctp_recvmsg error:: %s:%d",strerror(errno),errno);
if (sd < 0)
return -1;
memset((void*) &addr, 0, sizeof(struct sockaddr_in6));
from_len = (socklen_t) sizeof(struct sockaddr_in6);
memset((void*) &sinfo, 0, sizeof(struct sctp_sndrcvinfo));
int n = sctp_recvmsg(sd, (void*) buffer, SCTP_RECV_BUFFER_SIZE, (struct sockaddr*) &addr, &from_len, &sinfo, &flags);
if (n < 0) {
Logger::sctp().error("sctp_recvmsg error:: %s:%d", strerror(errno), errno);
return SCTP_RC_ERROR;
}
if (flags & MSG_NOTIFICATION) {
union sctp_notification *snp = (union sctp_notification *)buffer;
switch(snp->sn_header.sn_type){
case SCTP_SHUTDOWN_EVENT:{
union sctp_notification *snp = (union sctp_notification*) buffer;
switch (snp->sn_header.sn_type) {
case SCTP_SHUTDOWN_EVENT: {
Logger::sctp().debug("SCTP_SHUTDOWN_EVENT received");
break;
//return sctp_handle_com_down((sctp_assoc_id_t) snp->sn_shutdown_event.sse_assoc_id);
}
case SCTP_ASSOC_CHANGE:{
case SCTP_ASSOC_CHANGE: {
Logger::sctp().debug("SCTP association change event received");
return handle_assoc_change(sd, ppid, &snp->sn_assoc_change);
}
default:{
Logger::sctp().error("Unhandled notification type(%d)",snp->sn_header.sn_type);
default: {
Logger::sctp().error("Unhandled notification type(%d)", snp->sn_header.sn_type);
break;
}
}
}else{
} else {
sctp_association_t *association;
if ((association = sctp_is_assoc_in_list ((sctp_assoc_id_t) sinfo.sinfo_assoc_id)) == NULL) {
if ((association = sctp_is_assoc_in_list((sctp_assoc_id_t) sinfo.sinfo_assoc_id)) == NULL) {
return SCTP_RC_ERROR;
}
association->messages_recv++;
if (ntohl (sinfo.sinfo_ppid) != association->ppid) {
Logger::sctp().error("Received data from peer with unsollicited PPID(%d), expecting(%d)",ntohl (sinfo.sinfo_ppid), association->ppid);
if (ntohl(sinfo.sinfo_ppid) != association->ppid) {
Logger::sctp().error("Received data from peer with unsollicited PPID(%d), expecting(%d)", ntohl(sinfo.sinfo_ppid), association->ppid);
return SCTP_RC_ERROR;
}
Logger::sctp().info("[assoc_id(%d)][socket(%d)] Msg of length(%d) received from port(%d), on stream(%d), PPID(%d)",sinfo.sinfo_assoc_id, sd, n, ntohs (addr.sin6_port), sinfo.sinfo_stream, ntohl (sinfo.sinfo_ppid));
Logger::sctp().info("[assoc_id(%d)][socket(%d)] Msg of length(%d) received from port(%d), on stream(%d), PPID(%d)", sinfo.sinfo_assoc_id, sd, n, ntohs(addr.sin6_port), sinfo.sinfo_stream, ntohl(sinfo.sinfo_ppid));
bstring payload = blk2bstr(buffer, n);
//handle payload
app_->handle_receive(payload, (sctp_assoc_id_t) sinfo.sinfo_assoc_id, sinfo.sinfo_stream, association->instreams, association->outstreams);
}
}
int sctp_server::sctp_handle_com_down (sctp_assoc_id_t assoc_id){
}
int sctp_server::sctp_handle_reset(const sctp_assoc_id_t assoc_id){
}
}
//------------------------------------------------------------------------------
int sctp_server::sctp_handle_com_down(sctp_assoc_id_t assoc_id) {
}
int sctp_server::handle_assoc_change(int sd, uint32_t ppid, struct sctp_assoc_change *sctp_assoc_changed){
//------------------------------------------------------------------------------
int sctp_server::sctp_handle_reset(const sctp_assoc_id_t assoc_id) {
}
//------------------------------------------------------------------------------
int sctp_server::handle_assoc_change(int sd, uint32_t ppid, struct sctp_assoc_change *sctp_assoc_changed) {
int rc = SCTP_RC_NORMAL_READ;
switch (sctp_assoc_changed->sac_state) {
case SCTP_COMM_UP: {
if (add_new_association(sd, ppid, sctp_assoc_changed) == NULL) {
Logger::sctp().error("add new association with ppid(%d) socket(%d) error",ppid,sd);
Logger::sctp().error("add new association with ppid(%d) socket(%d) error", ppid, sd);
rc = SCTP_RC_ERROR;
}
break;
}
case SCTP_RESTART: {
if(sctp_is_assoc_in_list((sctp_assoc_id_t) sctp_assoc_changed->sac_assoc_id) != NULL){
if (sctp_is_assoc_in_list((sctp_assoc_id_t) sctp_assoc_changed->sac_assoc_id) != NULL) {
rc = sctp_handle_reset((sctp_assoc_id_t) sctp_assoc_changed->sac_assoc_id);
}
break;
......@@ -204,32 +227,34 @@ namespace sctp{
case SCTP_COMM_LOST:
case SCTP_SHUTDOWN_COMP:
case SCTP_CANT_STR_ASSOC: {
if(sctp_is_assoc_in_list((sctp_assoc_id_t) sctp_assoc_changed->sac_assoc_id) != NULL){
if (sctp_is_assoc_in_list((sctp_assoc_id_t) sctp_assoc_changed->sac_assoc_id) != NULL) {
rc = sctp_handle_com_down((sctp_assoc_id_t) sctp_assoc_changed->sac_assoc_id);
}
break;
}
default:
Logger::sctp().error("Logging unhandled sctp message(%d)",sctp_assoc_changed->sac_state);
Logger::sctp().error("Logging unhandled sctp message(%d)", sctp_assoc_changed->sac_state);
break;
}
return rc;
}
sctp_association_t* sctp_server::add_new_association(int sd, uint32_t ppid, struct sctp_assoc_change *sctp_assoc_changed) {
}
//------------------------------------------------------------------------------
sctp_association_t* sctp_server::add_new_association(int sd, uint32_t ppid, struct sctp_assoc_change *sctp_assoc_changed) {
sctp_association_t *new_association = NULL;
new_association = (sctp_association_t*)calloc (1, sizeof (sctp_association_t));
new_association = (sctp_association_t*) calloc(1, sizeof(sctp_association_t));
new_association->sd = sd;
new_association->ppid = ppid;
new_association->instreams = sctp_assoc_changed->sac_inbound_streams;
new_association->outstreams = sctp_assoc_changed->sac_outbound_streams;
new_association->assoc_id = (sctp_assoc_id_t) sctp_assoc_changed->sac_assoc_id;
Logger::sctp().debug("add new association with id(%d)",(sctp_assoc_id_t) sctp_assoc_changed->sac_assoc_id);
Logger::sctp().debug("add new association with id(%d)", (sctp_assoc_id_t) sctp_assoc_changed->sac_assoc_id);
sctp_ctx.push_back(new_association);
sctp_get_localaddresses(sd, NULL, NULL);
sctp_get_peeraddresses(sd, &new_association->peer_addresses, &new_association->nb_peer_addresses);
app_->handle_sctp_new_association(new_association->assoc_id, new_association->instreams, new_association->outstreams);
return new_association;
}
}
/*
sctp_association_t* sctp_server::sctp_add_new_peer (void){
sctp_association_t *new_sctp_descriptor = (sctp_association_t*)calloc (1, sizeof (sctp_association_t));
......@@ -251,24 +276,27 @@ namespace sctp{
//sctp_dump_list ();
return new_sctp_descriptor;
}
*/
sctp_association_t* sctp_server::sctp_is_assoc_in_list (sctp_assoc_id_t assoc_id){
*/
//------------------------------------------------------------------------------
sctp_association_t* sctp_server::sctp_is_assoc_in_list(sctp_assoc_id_t assoc_id) {
sctp_association_t *assoc_desc = NULL;
if (assoc_id < 0) {
return NULL;
}
for(int i=0; i<sctp_ctx.size();i++){
if(sctp_ctx[i]->assoc_id == assoc_id){
for (int i = 0; i < sctp_ctx.size(); i++) {
if (sctp_ctx[i]->assoc_id == assoc_id) {
return sctp_ctx[i];
}
}
return assoc_desc;
}
}
int sctp_server::sctp_get_peeraddresses(int sock, struct sockaddr **remote_addr, int *nb_remote_addresses){
//------------------------------------------------------------------------------
int sctp_server::sctp_get_peeraddresses(int sock, struct sockaddr **remote_addr, int *nb_remote_addresses) {
int nb;
struct sockaddr *temp_addr_p = NULL;
if ((nb = sctp_getpaddrs (sock, -1, &temp_addr_p)) <= 0) {
if ((nb = sctp_getpaddrs(sock, -1, &temp_addr_p)) <= 0) {
Logger::sctp().error("Failed to retrieve peer addresses");
return -1;
}
......@@ -276,18 +304,18 @@ namespace sctp{
Logger::sctp().info("Peer addresses:");
for (int j = 0; j < nb; j++) {
if (temp_addr_p[j].sa_family == AF_INET) {
char address[16] = {0};
char address[16] = { 0 };
struct sockaddr_in *addr = NULL;
addr = (struct sockaddr_in *)&temp_addr_p[j];
if (inet_ntop (AF_INET, &addr->sin_addr, address, sizeof (address)) != NULL) {
Logger::sctp().info( " - [%s]", address);
addr = (struct sockaddr_in*) &temp_addr_p[j];
if (inet_ntop(AF_INET, &addr->sin_addr, address, sizeof(address)) != NULL) {
Logger::sctp().info(" - [%s]", address);
}
} else {
struct sockaddr_in6 *addr = NULL;
char address[40] = {0};
addr = (struct sockaddr_in6 *)&temp_addr_p[j];
if (inet_ntop (AF_INET6, &addr->sin6_addr.s6_addr, address, sizeof (address)) != NULL) {
Logger::sctp().info( " - [%s]", address);
char address[40] = { 0 };
addr = (struct sockaddr_in6*) &temp_addr_p[j];
if (inet_ntop(AF_INET6, &addr->sin6_addr.s6_addr, address, sizeof(address)) != NULL) {
Logger::sctp().info(" - [%s]", address);
}
}
}
......@@ -296,36 +324,38 @@ namespace sctp{
*nb_remote_addresses = nb;
*remote_addr = temp_addr_p;
} else {
sctp_freepaddrs ((struct sockaddr *)temp_addr_p);
sctp_freepaddrs((struct sockaddr*) temp_addr_p);
}
return 0;
}
int sctp_server::sctp_get_localaddresses(int sock, struct sockaddr **local_addr, int *nb_local_addresses){
}
//------------------------------------------------------------------------------
int sctp_server::sctp_get_localaddresses(int sock, struct sockaddr **local_addr, int *nb_local_addresses) {
int nb = 0;
struct sockaddr * temp_addr_p = NULL;
if ((nb = sctp_getladdrs (sock, -1, &temp_addr_p)) <= 0) {
struct sockaddr *temp_addr_p = NULL;
if ((nb = sctp_getladdrs(sock, -1, &temp_addr_p)) <= 0) {
Logger::sctp().error("Failed to retrieve local addresses");
return -1;
}
if (temp_addr_p) {
Logger::sctp().info("----------------------");
Logger::sctp().info("Local addresses:");
for(int j=0; j<nb; j++){
for (int j = 0; j < nb; j++) {
if (temp_addr_p[j].sa_family == AF_INET) {
char address[16] = {0};
char address[16] = { 0 };
struct sockaddr_in *addr = NULL;
addr = (struct sockaddr_in *)&temp_addr_p[j];
if (inet_ntop (AF_INET, &addr->sin_addr, address, sizeof (address)) != NULL) {
Logger::sctp().info( " - [%s]", address);
addr = (struct sockaddr_in*) &temp_addr_p[j];
if (inet_ntop(AF_INET, &addr->sin_addr, address, sizeof(address)) != NULL) {
Logger::sctp().info(" - [%s]", address);
}
}else if(temp_addr_p[j].sa_family == AF_INET6){
} else if (temp_addr_p[j].sa_family == AF_INET6) {
struct sockaddr_in6 *addr = NULL;
char address[40] = {0};
addr = (struct sockaddr_in6 *)&temp_addr_p[j];
if (inet_ntop (AF_INET6, &addr->sin6_addr.s6_addr, address, sizeof (address)) != NULL) {
Logger::sctp().info( " - [%s]", address);
char address[40] = { 0 };
addr = (struct sockaddr_in6*) &temp_addr_p[j];
if (inet_ntop(AF_INET6, &addr->sin6_addr.s6_addr, address, sizeof(address)) != NULL) {
Logger::sctp().info(" - [%s]", address);
}
}else{
} else {
Logger::sctp().error(" - unhandled address family %d", temp_addr_p[j].sa_family);
}
}
......@@ -333,15 +363,17 @@ namespace sctp{
if (local_addr != NULL && nb_local_addresses != NULL) {
*nb_local_addresses = nb;
*local_addr = temp_addr_p;
}else{
sctp_freeladdrs ((struct sockaddr *)temp_addr_p);
} else {
sctp_freeladdrs((struct sockaddr*) temp_addr_p);
}
}
return 0;
}
int sctp_server::sctp_send_msg(sctp_assoc_id_t sctp_assoc_id, sctp_stream_id_t stream, bstring *payload){
}
//------------------------------------------------------------------------------
int sctp_server::sctp_send_msg(sctp_assoc_id_t sctp_assoc_id, sctp_stream_id_t stream, bstring *payload) {
sctp_association_t *assoc_desc = NULL;
if ((assoc_desc = sctp_is_assoc_in_list (sctp_assoc_id)) == NULL) {
if ((assoc_desc = sctp_is_assoc_in_list(sctp_assoc_id)) == NULL) {
Logger::sctp().error("This assoc id(%d) has not been fount in list", sctp_assoc_id);
return -1;
}
......@@ -350,8 +382,8 @@ namespace sctp{
return -1;
}
Logger::sctp().debug("[%d][%d] Sending buffer %p of %d bytes on stream %d with ppid %d", assoc_desc->sd, sctp_assoc_id, bdata(*payload), blength(*payload), stream, assoc_desc->ppid);
if (sctp_sendmsg (assoc_desc->sd, (const void *)bdata(*payload), (size_t) blength(*payload), NULL, 0, htonl(assoc_desc->ppid), 0, stream, 0, 0) < 0) {
Logger::sctp().error("send, sd:%u,stream:%u,ppid:%u, len:%u, failed: %s,%d",assoc_desc->sd,stream, htonl(assoc_desc->ppid), blength(*payload), strerror (errno), errno);
if (sctp_sendmsg(assoc_desc->sd, (const void*) bdata(*payload), (size_t) blength(*payload), NULL, 0, htonl(assoc_desc->ppid), 0, stream, 0, 0) < 0) {
Logger::sctp().error("send, sd:%u,stream:%u,ppid:%u, len:%u, failed: %s,%d", assoc_desc->sd, stream, htonl(assoc_desc->ppid), blength(*payload), strerror(errno), errno);
*payload = NULL;
return -1;
}
......@@ -359,7 +391,6 @@ namespace sctp{
*payload = NULL;
assoc_desc->messages_sent++;
return 0;
}
}
}
......@@ -31,10 +31,10 @@
#include "endpoint.hpp"
#include <thread>
extern "C"{
#include <netinet/in.h>
#include <netinet/sctp.h>
#include "bstrlib.h"
extern "C" {
#include <netinet/in.h>
#include <netinet/sctp.h>
#include "bstrlib.h"
}
#include <vector>
#include <iostream>
......@@ -45,7 +45,7 @@ using namespace std;
#define SCTP_RC_NORMAL_READ 0
#define SCTP_RC_DISCONNECT 1
namespace sctp{
namespace sctp {
typedef uint16_t sctp_stream_id_t;
typedef uint32_t sctp_assoc_id_t;
......@@ -63,7 +63,7 @@ typedef struct sctp_association_s {
struct sockaddr *peer_addresses; ///< A list of peer addresses
int nb_peer_addresses;
}sctp_association_t;
} sctp_association_t;
typedef struct sctp_descriptor_s {
// List of connected peers
......@@ -74,8 +74,8 @@ typedef struct sctp_descriptor_s {
uint16_t nb_outstreams;
} sctp_descriptor_t;
class sctp_application{
public:
class sctp_application {
public:
virtual void handle_receive(bstring payload, sctp_assoc_id_t assoc_id, sctp_stream_id_t stream, sctp_stream_id_t instreams, sctp_stream_id_t outstreams) = 0;
virtual void handle_sctp_new_association(sctp_assoc_id_t assoc_id, sctp_stream_id_t instreams, sctp_stream_id_t outstreams) = 0;
virtual uint32_t getPpid() = 0;
......@@ -85,26 +85,26 @@ public:
};
class sctp_server{
public:
sctp_server(const char * address, const uint16_t port_num);
class sctp_server {
public:
sctp_server(const char *address, const uint16_t port_num);
virtual ~sctp_server();
int create_socket (const char * address, const uint16_t port_num);
int create_socket(const char *address, const uint16_t port_num);
void start_receive(sctp_application *app);
int sctp_send_msg(sctp_assoc_id_t sctp_assoc_id, sctp_stream_id_t stream, bstring *payload);
private:
static void *sctp_receiver_thread(void * arg);
private:
static void* sctp_receiver_thread(void *arg);
int getSocket();
int sctp_read_from_socket(int sd, uint32_t m_ppid);
int handle_assoc_change(int sd, uint32_t ppid, struct sctp_assoc_change *assoc_change);
int sctp_handle_com_down (sctp_assoc_id_t assoc_id);
int sctp_handle_com_down(sctp_assoc_id_t assoc_id);
int sctp_handle_reset(const sctp_assoc_id_t assoc_id);
sctp_association_t *add_new_association(int sd, uint32_t ppid, struct sctp_assoc_change *sctp_assoc_changed);
sctp_association_t *sctp_add_new_peer (void);
sctp_association_t* add_new_association(int sd, uint32_t ppid, struct sctp_assoc_change *sctp_assoc_changed);
sctp_association_t* sctp_add_new_peer(void);
int sctp_get_localaddresses(int sock, struct sockaddr **local_addr, int *nb_local_addresses);
int sctp_get_peeraddresses(int sock, struct sockaddr **remote_addr, int *nb_remote_addresses);
sctp_association_t *sctp_is_assoc_in_list (sctp_assoc_id_t assoc_id);
private:
sctp_association_t* sctp_is_assoc_in_list(sctp_assoc_id_t assoc_id);
private:
int socket_;
sctp_application *app_;
pthread_t thread_;
......
......@@ -38,25 +38,26 @@
#include "OCTET_STRING.h"
extern void print_buffer(const std::string app, const std::string commit, uint8_t *buf, int len);
extern void hexStr2Byte(const char* src, unsigned char *dest, int len);
extern void hexStr2Byte(const char *src, unsigned char *dest, int len);
//------------------------------------------------------------------------------
/************ algorithm f1 **************/
/*
Computes network authentication code MAC-A from key K, random, challenge RAND, sequence number SQN and authentication management field AMF.
*/
void Authentication_5gaka::f1 ( const uint8_t opc[16],const uint8_t k[16], const uint8_t _rand[16], const uint8_t sqn[6], const uint8_t amf[2], uint8_t mac_a[8] ){
*/
void Authentication_5gaka::f1(const uint8_t opc[16], const uint8_t k[16], const uint8_t _rand[16], const uint8_t sqn[6], const uint8_t amf[2], uint8_t mac_a[8]) {
uint8_t temp[16];
uint8_t in1[16];
uint8_t out1[16];
uint8_t rijndaelInput[16];
uint8_t i;
RijndaelKeySchedule (k);
RijndaelKeySchedule(k);
for (i = 0; i < 16; i++)
rijndaelInput[i] = _rand[i] ^ opc[i];
RijndaelEncrypt (rijndaelInput, temp);
RijndaelEncrypt(rijndaelInput, temp);
for (i = 0; i < 6; i++) {
in1[i] = sqn[i];
......@@ -81,7 +82,7 @@ void Authentication_5gaka::f1 ( const uint8_t opc[16],const uint8_t k[16], const
for (i = 0; i < 16; i++)
rijndaelInput[i] ^= temp[i];
RijndaelEncrypt (rijndaelInput, out1);
RijndaelEncrypt(rijndaelInput, out1);
for (i = 0; i < 16; i++)
out1[i] ^= opc[i];
......@@ -91,26 +92,26 @@ void Authentication_5gaka::f1 ( const uint8_t opc[16],const uint8_t k[16], const
return;
}
//------------------------------------------------------------------------------
/*-------------------------------------------------------------------
Algorithms f2-f5
-------------------------------------------------------------------
Takes key K and random challenge RAND, and returns response RES,
confidentiality key CK, integrity key IK and anonymity key AK.
-----------------------------------------------------------------*/
void Authentication_5gaka::f2345 ( const uint8_t opc[16],const uint8_t k[16], const uint8_t _rand[16], uint8_t res[8], uint8_t ck[16], uint8_t ik[16], uint8_t ak[6] ){
void Authentication_5gaka::f2345(const uint8_t opc[16], const uint8_t k[16], const uint8_t _rand[16], uint8_t res[8], uint8_t ck[16], uint8_t ik[16], uint8_t ak[6]) {
uint8_t temp[16];
uint8_t out[16];
uint8_t rijndaelInput[16];
uint8_t i;
RijndaelKeySchedule (k);
RijndaelKeySchedule(k);
for (i = 0; i < 16; i++)
rijndaelInput[i] = _rand[i] ^ opc[i];
RijndaelEncrypt (rijndaelInput, temp);
RijndaelEncrypt(rijndaelInput, temp);
/*
* To obtain output block OUT2: XOR OPc and TEMP,
......@@ -121,7 +122,7 @@ void Authentication_5gaka::f2345 ( const uint8_t opc[16],const uint8_t k[16], co
rijndaelInput[i] = temp[i] ^ opc[i];
rijndaelInput[15] ^= 1;
RijndaelEncrypt (rijndaelInput, out);
RijndaelEncrypt(rijndaelInput, out);
for (i = 0; i < 16; i++)
out[i] ^= opc[i];
......@@ -141,7 +142,7 @@ void Authentication_5gaka::f2345 ( const uint8_t opc[16],const uint8_t k[16], co
rijndaelInput[(i + 12) % 16] = temp[i] ^ opc[i];
rijndaelInput[15] ^= 2;
RijndaelEncrypt (rijndaelInput, out);
RijndaelEncrypt(rijndaelInput, out);
for (i = 0; i < 16; i++)
out[i] ^= opc[i];
......@@ -158,7 +159,7 @@ void Authentication_5gaka::f2345 ( const uint8_t opc[16],const uint8_t k[16], co
rijndaelInput[(i + 8) % 16] = temp[i] ^ opc[i];
rijndaelInput[15] ^= 4;
RijndaelEncrypt (rijndaelInput, out);
RijndaelEncrypt(rijndaelInput, out);
for (i = 0; i < 16; i++)
out[i] ^= opc[i];
......@@ -172,26 +173,24 @@ void Authentication_5gaka::f2345 ( const uint8_t opc[16],const uint8_t k[16], co
/*-------------------------------------------------------------------
Algorithm f1
-------------------------------------------------------------------
Computes resynch authentication code MAC-S from key K, random
challenge RAND, sequence number SQN and authentication management
field AMF.
-----------------------------------------------------------------*/
void Authentication_5gaka::f1star(const uint8_t opc[16], const uint8_t k[16], const uint8_t _rand[16], const uint8_t sqn[6], const uint8_t amf[2], uint8_t mac_s[8]){
void Authentication_5gaka::f1star(const uint8_t opc[16], const uint8_t k[16], const uint8_t _rand[16], const uint8_t sqn[6], const uint8_t amf[2], uint8_t mac_s[8]) {
uint8_t temp[16];
uint8_t in1[16];
uint8_t out1[16];
uint8_t rijndaelInput[16];
uint8_t i;
RijndaelKeySchedule (k);
RijndaelKeySchedule(k);
for (i = 0; i < 16; i++)
rijndaelInput[i] = _rand[i] ^ opc[i];
RijndaelEncrypt (rijndaelInput, temp);
RijndaelEncrypt(rijndaelInput, temp);
for (i = 0; i < 6; i++) {
in1[i] = sqn[i];
......@@ -216,7 +215,7 @@ void Authentication_5gaka::f1star(const uint8_t opc[16], const uint8_t k[16], co
for (i = 0; i < 16; i++)
rijndaelInput[i] ^= temp[i];
RijndaelEncrypt (rijndaelInput, out1);
RijndaelEncrypt(rijndaelInput, out1);
for (i = 0; i < 16; i++)
out1[i] ^= opc[i];
......@@ -230,23 +229,22 @@ void Authentication_5gaka::f1star(const uint8_t opc[16], const uint8_t k[16], co
/*-------------------------------------------------------------------
Algorithm f5
-------------------------------------------------------------------
Takes key K and random challenge RAND, and returns resynch
anonymity key AK.
-----------------------------------------------------------------*/
void Authentication_5gaka::f5star(const uint8_t opc[16], const uint8_t k[16], const uint8_t _rand[16], uint8_t ak[6]){
void Authentication_5gaka::f5star(const uint8_t opc[16], const uint8_t k[16], const uint8_t _rand[16], uint8_t ak[6]) {
uint8_t temp[16];
uint8_t out[16];
uint8_t rijndaelInput[16];
uint8_t i;
RijndaelKeySchedule (k);
RijndaelKeySchedule(k);
for (i = 0; i < 16; i++)
rijndaelInput[i] = _rand[i] ^ opc[i];
RijndaelEncrypt (rijndaelInput, temp);
RijndaelEncrypt(rijndaelInput, temp);
/*
* To obtain output block OUT5: XOR OPc and TEMP,
......@@ -257,7 +255,7 @@ void Authentication_5gaka::f5star(const uint8_t opc[16], const uint8_t k[16], co
rijndaelInput[(i + 4) % 16] = temp[i] ^ opc[i];
rijndaelInput[15] ^= 8;
RijndaelEncrypt (rijndaelInput, out);
RijndaelEncrypt(rijndaelInput, out);
for (i = 0; i < 16; i++)
out[i] ^= opc[i];
......@@ -271,12 +269,12 @@ void Authentication_5gaka::f5star(const uint8_t opc[16], const uint8_t k[16], co
/*-------------------------------------------------------------------
Function to compute OPc from OP and K.
-----------------------------------------------------------------*/
void Authentication_5gaka::ComputeOPc(const uint8_t kP[16], const uint8_t opP[16], uint8_t opcP[16]){
void Authentication_5gaka::ComputeOPc(const uint8_t kP[16], const uint8_t opP[16], uint8_t opcP[16]) {
uint8_t i;
RijndaelKeySchedule (kP);
RijndaelKeySchedule(kP);
//FPRINTF_DEBUG ("Compute opc:\n\tK:\t%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n", kP[0], kP[1], kP[2], kP[3], kP[4], kP[5], kP[6], kP[7], kP[8], kP[9], kP[10], kP[11], kP[12], kP[13], kP[14], kP[15]);
RijndaelEncrypt (opP, opcP);
RijndaelEncrypt(opP, opcP);
//FPRINTF_DEBUG ("\tIn:\t%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n\tRinj:\t%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n",
// opP[0], opP[1], opP[2], opP[3], opP[4], opP[5], opP[6], opP[7],
// opP[8], opP[9], opP[10], opP[11], opP[12], opP[13], opP[14], opP[15], opcP[0], opcP[1], opcP[2], opcP[3], opcP[4], opcP[5], opcP[6], opcP[7], opcP[8], opcP[9], opcP[10], opcP[11], opcP[12], opcP[13], opcP[14], opcP[15]);
......@@ -288,99 +286,106 @@ void Authentication_5gaka::ComputeOPc(const uint8_t kP[16], const uint8_t opP[16
return;
}
void Authentication_5gaka::generate_autn(const uint8_t sqn[6], const uint8_t ak[6], const uint8_t amf[2], const uint8_t mac_a[8], uint8_t autn[16]){
for(int i=0; i<6; i++){
//------------------------------------------------------------------------------
void Authentication_5gaka::generate_autn(const uint8_t sqn[6], const uint8_t ak[6], const uint8_t amf[2], const uint8_t mac_a[8], uint8_t autn[16]) {
for (int i = 0; i < 6; i++) {
autn[i] = sqn[i] ^ ak[i];
}
memcpy (&autn[6], amf, 2);
memcpy (&autn[8], mac_a, 8);
memcpy(&autn[6], amf, 2);
memcpy(&autn[8], mac_a, 8);
}
void Authentication_5gaka::kdf(uint8_t * key, uint16_t key_len, uint8_t * s, uint16_t s_len, uint8_t * out, uint16_t out_len){
//------------------------------------------------------------------------------
void Authentication_5gaka::kdf(uint8_t *key, uint16_t key_len, uint8_t *s, uint16_t s_len, uint8_t *out, uint16_t out_len) {
struct hmac_sha256_ctx ctx;
memset (&ctx, 0, sizeof (ctx));
hmac_sha256_set_key (&ctx, key_len, key);
hmac_sha256_update (&ctx, s_len, s);
hmac_sha256_digest (&ctx, out_len, out);
memset(&ctx, 0, sizeof(ctx));
hmac_sha256_set_key(&ctx, key_len, key);
hmac_sha256_update(&ctx, s_len, s);
hmac_sha256_digest(&ctx, out_len, out);
}
void Authentication_5gaka::derive_kseaf(std::string serving_network, uint8_t kausf[32], uint8_t kseaf[32]){
//------------------------------------------------------------------------------
void Authentication_5gaka::derive_kseaf(std::string serving_network, uint8_t kausf[32], uint8_t kseaf[32]) {
Logger::amf_n1().debug("derive_kseaf ...");
OCTET_STRING_t netName;
OCTET_STRING_fromBuf(&netName, serving_network.c_str(), serving_network.length());
uint8_t S[100];
S[0] = 0x6C;//FC
S[0] = 0x6C; //FC
memcpy(&S[1], netName.buf, netName.size);
//memcpy (&S[1+netName.size], &netName.size, 2);
S[1+netName.size] = (uint8_t)((netName.size & 0xff00) >> 8);
S[2+netName.size] = (uint8_t)(netName.size & 0x00ff);
kdf(kausf, 32, S, 3+netName.size, kseaf, 32);
S[1 + netName.size] = (uint8_t)((netName.size & 0xff00) >> 8);
S[2 + netName.size] = (uint8_t)(netName.size & 0x00ff);
kdf(kausf, 32, S, 3 + netName.size, kseaf, 32);
Logger::amf_n1().debug("derive kseaf finished!");
}
void Authentication_5gaka::derive_kausf(uint8_t ck[16], uint8_t ik[16], std::string serving_network, uint8_t sqn[6], uint8_t ak[6], uint8_t kausf[32]){
//------------------------------------------------------------------------------
void Authentication_5gaka::derive_kausf(uint8_t ck[16], uint8_t ik[16], std::string serving_network, uint8_t sqn[6], uint8_t ak[6], uint8_t kausf[32]) {
Logger::amf_n1().debug("derive_kausf ...");
OCTET_STRING_t netName;
OCTET_STRING_fromBuf(&netName, serving_network.c_str(), serving_network.length());
uint8_t S[100];
uint8_t key[32];
memcpy (&key[0], ck, 16);
memcpy (&key[16], ik, 16);//KEY
memcpy(&key[0], ck, 16);
memcpy(&key[16], ik, 16); //KEY
S[0] = 0x6A;
memcpy (&S[1], netName.buf, netName.size);
memcpy(&S[1], netName.buf, netName.size);
//memcpy (&S[1+netName.size], &netName.size, 2);
S[1+netName.size] = (uint8_t)((netName.size & 0xff00) >> 8);
S[2+netName.size] = (uint8_t)(netName.size & 0x00ff);
for(int i=0; i<6; i++){
S[3+netName.size+i] = sqn[i] ^ ak[i];
S[1 + netName.size] = (uint8_t)((netName.size & 0xff00) >> 8);
S[2 + netName.size] = (uint8_t)(netName.size & 0x00ff);
for (int i = 0; i < 6; i++) {
S[3 + netName.size + i] = sqn[i] ^ ak[i];
}
S[9+netName.size] = 0x00;
S[10+netName.size] = 0x06;
kdf(key, 32, S, 11+netName.size, kausf, 32);
S[9 + netName.size] = 0x00;
S[10 + netName.size] = 0x06;
kdf(key, 32, S, 11 + netName.size, kausf, 32);
}
void Authentication_5gaka::derive_kamf(std::string imsi, uint8_t *kseaf, uint8_t *kamf, uint16_t abba){
//------------------------------------------------------------------------------
void Authentication_5gaka::derive_kamf(std::string imsi, uint8_t *kseaf, uint8_t *kamf, uint16_t abba) {
Logger::amf_n1().debug("derive_kamf ...");
std::string ueSupi = imsi;//OK
std::string ueSupi = imsi; //OK
OCTET_STRING_t supi;
OCTET_STRING_fromBuf(&supi, ueSupi.c_str(), ueSupi.length());
int supiLen = supi.size;
uint8_t S[100];
S[0] = 0x6D;//FC = 0x6D
memcpy (&S[1], supi.buf, supiLen);
S[0] = 0x6D; //FC = 0x6D
memcpy(&S[1], supi.buf, supiLen);
//memcpy (&S[1+supiLen], &supiLen, 2);
S[1+supiLen] = (uint8_t)((supiLen & 0xff00) >> 8);
S[2+supiLen] = (uint8_t)(supiLen & 0x00ff);
S[3+supiLen] = abba & 0x00ff;
S[4+supiLen] = (abba & 0xff00)>>8;
S[5+supiLen] = 0x00;
S[6+supiLen] = 0x02;
kdf(kseaf, 32, S, 7+supiLen, kamf, 32);
S[1 + supiLen] = (uint8_t)((supiLen & 0xff00) >> 8);
S[2 + supiLen] = (uint8_t)(supiLen & 0x00ff);
S[3 + supiLen] = abba & 0x00ff;
S[4 + supiLen] = (abba & 0xff00) >> 8;
S[5 + supiLen] = 0x00;
S[6 + supiLen] = 0x02;
kdf(kseaf, 32, S, 7 + supiLen, kamf, 32);
}
void Authentication_5gaka::derive_knas(algorithm_type_dist_t nas_alg_type, uint8_t nas_alg_id, uint8_t kamf[32], uint8_t * knas){
//------------------------------------------------------------------------------
void Authentication_5gaka::derive_knas(algorithm_type_dist_t nas_alg_type, uint8_t nas_alg_id, uint8_t kamf[32], uint8_t *knas) {
Logger::amf_n1().debug("derive_knas ...");
uint8_t S[20];
uint8_t out[32] = {0};
S[0] = 0x69;//FC
S[1] = (uint8_t) (nas_alg_type & 0xFF);
uint8_t out[32] = { 0 };
S[0] = 0x69; //FC
S[1] = (uint8_t)(nas_alg_type & 0xFF);
S[2] = 0x00;
S[3] = 0x01;
S[4] = nas_alg_id;
S[5] = 0x00;
S[6] = 0x01;
kdf (kamf, 32, S, 7, out, 32);
kdf(kamf, 32, S, 7, out, 32);
//memcpy (knas, &out[31 - 16 + 1], 16);
for(int i=0; i<16; i++)
knas[i] = out[16+i];
for (int i = 0; i < 16; i++)
knas[i] = out[16 + i];
Logger::amf_n1().debug("derive knas finished!");
}
void Authentication_5gaka::derive_kgnb(uint32_t uplinkCount, uint8_t accessType, uint8_t kamf[32], uint8_t * kgnb){
//------------------------------------------------------------------------------
void Authentication_5gaka::derive_kgnb(uint32_t uplinkCount, uint8_t accessType, uint8_t kamf[32], uint8_t *kgnb) {
Logger::amf_n1().debug("derive_kgnb ...");
uint8_t S[20];
S[0] = 0x6E;
*(uint32_t*)(S+1) = htonl(uplinkCount);
*(uint32_t*) (S + 1) = htonl(uplinkCount);
S[5] = 0x00;
S[6] = 0x04;
S[7] = accessType;
......@@ -389,12 +394,13 @@ void Authentication_5gaka::derive_kgnb(uint32_t uplinkCount, uint8_t accessType,
kdf(kamf, 32, S, 10, kgnb, 32);
}
void Authentication_5gaka::derive_kasme(uint8_t ck[16], uint8_t ik[16], uint8_t plmn[3], uint8_t sqn[6], uint8_t ak[6], uint8_t * kasme){
//------------------------------------------------------------------------------
void Authentication_5gaka::derive_kasme(uint8_t ck[16], uint8_t ik[16], uint8_t plmn[3], uint8_t sqn[6], uint8_t ak[6], uint8_t *kasme) {
uint8_t s[14];
int i;
uint8_t key[32];
memcpy (&key[0], ck, 16);
memcpy (&key[16], ik, 16);
memcpy(&key[0], ck, 16);
memcpy(&key[16], ik, 16);
/*
* FC
*/
......@@ -406,7 +412,7 @@ void Authentication_5gaka::derive_kasme(uint8_t ck[16], uint8_t ik[16], uint8_t
* * * * 2 MNC digit 3 | MCC digit 3
* * * * 3 MNC digit 2 | MNC digit 1
*/
memcpy (&s[1], plmn, 3);
memcpy(&s[1], plmn, 3);
/*
* L0
*/
......@@ -424,10 +430,11 @@ void Authentication_5gaka::derive_kasme(uint8_t ck[16], uint8_t ik[16], uint8_t
*/
s[12] = 0x00;
s[13] = 0x06;
kdf (key, 32, s, 14, kasme, 32);
kdf(key, 32, s, 14, kasme, 32);
}
int Authentication_5gaka::generate_vector(const uint8_t opc[16], uint64_t imsi, uint8_t key[16], uint8_t plmn[3], uint8_t sqn[6], auc_vector_t * vector){
//------------------------------------------------------------------------------
int Authentication_5gaka::generate_vector(const uint8_t opc[16], uint64_t imsi, uint8_t key[16], uint8_t plmn[3], uint8_t sqn[6], auc_vector_t *vector) {
uint8_t amf[] = { 0x80, 0x00 };
uint8_t mac_a[8];
uint8_t ck[16];
......@@ -441,38 +448,39 @@ int Authentication_5gaka::generate_vector(const uint8_t opc[16], uint64_t imsi,
/*
* Compute MAC
*/
f1 (opc, key, vector->rand, sqn, amf, mac_a);
f1(opc, key, vector->rand, sqn, amf, mac_a);
/*
* Compute XRES, CK, IK, AK
*/
f2345 (opc, key, vector->rand, vector->xres, ck, ik, ak);
f2345(opc, key, vector->rand, vector->xres, ck, ik, ak);
/*
* AUTN = SQN ^ AK || AMF || MAC
*/
generate_autn (sqn, ak, amf, mac_a, vector->autn);
generate_autn(sqn, ak, amf, mac_a, vector->autn);
//print_buffer ("AUTN : ", vector->autn, 16);
derive_kasme (ck, ik, plmn, sqn, ak, vector->kasme);
derive_kasme(ck, ik, plmn, sqn, ak, vector->kasme);
//print_buffer ("KASME : ", vector->kasme, 32);
return 0;
}
uint8_t* Authentication_5gaka::sqn_ms_derive (const uint8_t opc[16], uint8_t * key, uint8_t * auts, uint8_t * rand_p){
//------------------------------------------------------------------------------
uint8_t* Authentication_5gaka::sqn_ms_derive(const uint8_t opc[16], uint8_t *key, uint8_t *auts, uint8_t *rand_p) {
/*
* AUTS = Conc(SQN MS ) || MAC-S
* * * * Conc(SQN MS ) = SQN MS ^ f5* (RAND)
* * * * MAC-S = f1* (SQN MS || RAND || AMF)
*/
uint8_t ak[6] = {0};
uint8_t ak[6] = { 0 };
uint8_t *conc_sqn_ms = NULL;
uint8_t *mac_s = NULL;
uint8_t mac_s_computed[MAC_S_LENGTH] = {0};
uint8_t mac_s_computed[MAC_S_LENGTH] = { 0 };
uint8_t *sqn_ms = NULL;
uint8_t amf[2] = { 0, 0 };
int i = 0;
conc_sqn_ms = auts;
mac_s = &auts[6];
sqn_ms = (uint8_t*)malloc (SQN_LENGTH_OCTEST);
sqn_ms = (uint8_t*) malloc(SQN_LENGTH_OCTEST);
/*
* if (hss_config.valid_opc == 0) {
* SetOP(hss_config.operator_key);
......@@ -481,17 +489,17 @@ uint8_t* Authentication_5gaka::sqn_ms_derive (const uint8_t opc[16], uint8_t * k
/*
* Derive AK from key and rand
*/
f5star (opc, key, rand_p, ak);
f5star(opc, key, rand_p, ak);
for (i = 0; i < 6; i++) {
sqn_ms[i] = ak[i] ^ conc_sqn_ms[i];
}
f1star (opc, key, rand_p, sqn_ms, amf, mac_s_computed);
f1star(opc, key, rand_p, sqn_ms, amf, mac_s_computed);
if (memcmp (mac_s_computed, mac_s, 8) != 0) {
if (memcmp(mac_s_computed, mac_s, 8) != 0) {
//FPRINTF_ERROR ( "Failed to verify computed SQN_MS\n");
free (sqn_ms);
free(sqn_ms);
return NULL;
}
......
......@@ -30,12 +30,12 @@
#define _5GAKA_H_
//extern "C"{
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include <gmp.h>
#include <pthread.h>
#include <string>
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include <gmp.h>
#include <pthread.h>
#include <string>
//}
#define SQN_LENGTH_BITS (48)
......@@ -60,23 +60,23 @@ typedef struct {
uint8_t kasme[32];
} auc_vector_t;
typedef struct{
typedef struct {
uint8_t avType;
uint8_t rand[16];
uint8_t xres[8];
uint8_t xresStar[16];
uint8_t autn[16];
uint8_t kausf[32];
}_5G_HE_AV_t;//clause 6.3.6.2.5, ts33.501
} _5G_HE_AV_t; //clause 6.3.6.2.5, ts33.501
typedef struct{
typedef struct {
uint8_t avType;
uint8_t rand[16];
uint8_t hxres[16];
uint8_t hxresStar[16];
uint8_t autn[16];
uint8_t kseaf[32];
}_5G_AV_t;
} _5G_AV_t;
typedef struct random_state_s {
pthread_mutex_t lock;
......@@ -101,59 +101,46 @@ typedef enum {
UP_INT_ALG = 0x06
} algorithm_type_dist_t;
class Authentication_5gaka{
public:
/****** sequence number functions ********/
class Authentication_5gaka {
public:
/****** sequence number functions ********/
//struct sqn_ue_s *sqn_exists(uint64_t imsi);
//void sqn_insert(struct sqn_ue_s *item);
//void sqn_init(struct sqn_ue_s *item);
//struct sqn_ue_s *sqn_new(uint64_t imsi);
//void sqn_list_init(void);
//void sqn_get(uint64_t imsi, uint8_t sqn[6]);
public:
/****** random number functions *********/
public:
/****** random number functions *********/
//void random_init(void);
//void generate_random(uint8_t *random, ssize_t length);
public:
/****** internal algorithms f1 f2 f3 f4 f5 ********/
static void f1 ( const uint8_t opc[16],const uint8_t k[16], const uint8_t _rand[16], const uint8_t sqn[6], const uint8_t amf[2], uint8_t mac_a[8] );
static void f1star( const uint8_t kP[16],const uint8_t k[16], const uint8_t rand[16], const uint8_t sqn[6], const uint8_t amf[2], uint8_t mac_s[8] );
static void f2345 ( const uint8_t opc[16],const uint8_t k[16], const uint8_t _rand[16], uint8_t res[8], uint8_t ck[16], uint8_t ik[16], uint8_t ak[6] );
static void f5star( const uint8_t kP[16],const uint8_t k[16], const uint8_t rand[16], uint8_t ak[6] );
public:
/****** key derive ***********/
public:
/****** internal algorithms f1 f2 f3 f4 f5 ********/
static void f1(const uint8_t opc[16], const uint8_t k[16], const uint8_t _rand[16], const uint8_t sqn[6], const uint8_t amf[2], uint8_t mac_a[8]);
static void f1star(const uint8_t kP[16], const uint8_t k[16], const uint8_t rand[16], const uint8_t sqn[6], const uint8_t amf[2], uint8_t mac_s[8]);
static void f2345(const uint8_t opc[16], const uint8_t k[16], const uint8_t _rand[16], uint8_t res[8], uint8_t ck[16], uint8_t ik[16], uint8_t ak[6]);
static void f5star(const uint8_t kP[16], const uint8_t k[16], const uint8_t rand[16], uint8_t ak[6]);
public:
/****** key derive ***********/
static void kdf(uint8_t *key, uint16_t key_len, uint8_t *s, uint16_t s_len, uint8_t *out, uint16_t out_len);
static void derive_kasme(uint8_t ck[16], uint8_t ik[16], uint8_t plmn[3], uint8_t sqn[6], uint8_t ak[6], uint8_t kasme[32]);
static void derive_kausf(uint8_t ck[16], uint8_t ik[16], std::string serving_network, uint8_t sqn[6], uint8_t ak[6], uint8_t kausf[32]);
static void derive_kseaf(std::string serving_network, uint8_t kausf[32], uint8_t kseaf[32]);
static void derive_kamf(std::string imsi, uint8_t *kseaf, uint8_t *kamf, uint16_t abba);
static void derive_knas(algorithm_type_dist_t nas_alg_type, uint8_t nas_alg_id, uint8_t kamf[32], uint8_t * knas);
static void derive_kgnb(uint32_t uplinkCount, uint8_t accessType, uint8_t kamf[32], uint8_t * kgnb);
static uint8_t *sqn_ms_derive(const uint8_t opc[16], uint8_t *key, uint8_t *auts, uint8_t *rand);
public:
/****** general functions ********/
static void ComputeOPc( const uint8_t kP[16], const uint8_t opP[16], uint8_t opcP[16] );
static void derive_knas(algorithm_type_dist_t nas_alg_type, uint8_t nas_alg_id, uint8_t kamf[32], uint8_t *knas);
static void derive_kgnb(uint32_t uplinkCount, uint8_t accessType, uint8_t kamf[32], uint8_t *kgnb);
static uint8_t* sqn_ms_derive(const uint8_t opc[16], uint8_t *key, uint8_t *auts, uint8_t *rand);
public:
/****** general functions ********/
static void ComputeOPc(const uint8_t kP[16], const uint8_t opP[16], uint8_t opcP[16]);
static void generate_autn(const uint8_t sqn[6], const uint8_t ak[6], const uint8_t amf[2], const uint8_t mac_a[8], uint8_t autn[16]);
static int generate_vector(const uint8_t opc[16], uint64_t imsi, uint8_t key[16], uint8_t plmn[3], uint8_t sqn[6], auc_vector_t *vector);
public:
/****** Rijndael ********/
public:
/****** Rijndael ********/
static void RijndaelKeySchedule(const uint8_t key[16]);
static void RijndaelEncrypt(const uint8_t in[16], uint8_t out[16]);
private:
private:
auc_vector_t auc_vector;
};
#endif
......@@ -71,23 +71,20 @@ u8 Xtime[256] = {
251, 249, 255, 253, 243, 241, 247, 245, 235, 233, 239, 237, 227, 225, 231, 229
};
void Authentication_5gaka::RijndaelKeySchedule(const uint8_t key[16]){
//------------------------------------------------------------------------------
void Authentication_5gaka::RijndaelKeySchedule(const uint8_t key[16]) {
u8 roundConst;
/******* first round key equals key ********/
for(int i=0; i<16; i++){
for (int i = 0; i < 16; i++) {
roundKeys[0][i & 0x03][i >> 2] = key[i];
}
roundConst = 1;
for(int i=1; i<11; i++){
roundKeys[i][0][0] = S[roundKeys[i - 1][1][3]]
^ roundKeys[i - 1][0][0] ^ roundConst;
roundKeys[i][1][0] = S[roundKeys[i - 1][2][3]]
^ roundKeys[i - 1][1][0];
roundKeys[i][2][0] = S[roundKeys[i - 1][3][3]]
^ roundKeys[i - 1][2][0];
roundKeys[i][3][0] = S[roundKeys[i - 1][0][3]]
^ roundKeys[i - 1][3][0];
for(int j=0; j<4; j++){
for (int i = 1; i < 11; i++) {
roundKeys[i][0][0] = S[roundKeys[i - 1][1][3]] ^ roundKeys[i - 1][0][0] ^ roundConst;
roundKeys[i][1][0] = S[roundKeys[i - 1][2][3]] ^ roundKeys[i - 1][1][0];
roundKeys[i][2][0] = S[roundKeys[i - 1][3][3]] ^ roundKeys[i - 1][2][0];
roundKeys[i][3][0] = S[roundKeys[i - 1][0][3]] ^ roundKeys[i - 1][3][0];
for (int j = 0; j < 4; j++) {
roundKeys[i][j][1] = roundKeys[i - 1][j][1] ^ roundKeys[i][j][0];
roundKeys[i][j][2] = roundKeys[i - 1][j][2] ^ roundKeys[i][j][1];
roundKeys[i][j][3] = roundKeys[i - 1][j][3] ^ roundKeys[i][j][2];
......@@ -113,20 +110,24 @@ void Authentication_5gaka::RijndaelKeySchedule(const uint8_t key[16]){
}
/************ internal functions ******************/
void KeyAdd(u8 state[4][4], u8 roundKeys[11][4][4], int round){
for(int i=0; i<4; i++)
for(int j=0; j<4; j++)
//------------------------------------------------------------------------------
void KeyAdd(u8 state[4][4], u8 roundKeys[11][4][4], int round) {
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
state[i][j] ^= roundKeys[round][i][j];
return;
}
int ByteSub(u8 state[4][4]){
for(int i=0; i<4; i++)
for(int j=0; j<4; j++)
//------------------------------------------------------------------------------
int ByteSub(u8 state[4][4]) {
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
state[i][j] = S[state[i][j]];
return 0;
}
void ShiftRow(u8 state[4][4]){
//------------------------------------------------------------------------------
void ShiftRow(u8 state[4][4]) {
u8 temp;
/*
* left rotate row 1 by 1
......@@ -155,9 +156,11 @@ void ShiftRow(u8 state[4][4]){
state[3][1] = temp;
return;
}
void MixColumn (u8 state[4][4]){
//------------------------------------------------------------------------------
void MixColumn(u8 state[4][4]) {
u8 temp, tmp, tmp0;
for(int i=0; i<4; i++){
for (int i = 0; i < 4; i++) {
temp = state[0][i] ^ state[1][i] ^ state[2][i] ^ state[3][i];
tmp0 = state[0][i];
/*
......@@ -174,28 +177,29 @@ void MixColumn (u8 state[4][4]){
}
return;
}
/*-------------------------------------------------------------------
Rijndael encryption function. Takes 16-byte input and creates
16-byte output (using round keys already derived from 16-byte
key).
-----------------------------------------------------------------*/
void Authentication_5gaka::RijndaelEncrypt(const uint8_t input[16], uint8_t output[16]){
int i=0, r=0;
void Authentication_5gaka::RijndaelEncrypt(const uint8_t input[16], uint8_t output[16]) {
int i = 0, r = 0;
u8 state[4][4];
for(i=0; i< 16; i++)
for (i = 0; i < 16; i++)
state[i & 0x3][i >> 2] = input[i];
KeyAdd(state, roundKeys, 0);
#if AUTH_ALG_ON
printf("end of round(%d)\n0x", 0);
#endif
for(int i=0; i<16; i++)
for (int i = 0; i < 16; i++)
printf("%x ", state[i & 0x3][i >> 2]);
printf("\n");
for (r = 1; r <= 9; r++) {
ByteSub (state);
ShiftRow (state);
MixColumn (state);
KeyAdd (state, roundKeys, r);
ByteSub(state);
ShiftRow(state);
MixColumn(state);
KeyAdd(state, roundKeys, r);
#if AUTH_ALG_ON
printf("end of round(%d)\n0x", r);
for (i = 0; i < 16; i++)
......@@ -203,9 +207,9 @@ void Authentication_5gaka::RijndaelEncrypt(const uint8_t input[16], uint8_t outp
printf("\n");
#endif
}
ByteSub (state);
ShiftRow (state);
KeyAdd (state, roundKeys, r);
ByteSub(state);
ShiftRow(state);
KeyAdd(state, roundKeys, r);
#if AUTH_ALG_ON
printf("end of round(%d)\n0x", r);
for(int i=0; i<16; i++)
......
......@@ -51,8 +51,8 @@ const unsigned int Sha256::sha256_k[64] = //UL = uint32
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
void Sha256::transform(const unsigned char *message, unsigned int block_nb)
{
//------------------------------------------------------------------------------
void Sha256::transform(const unsigned char *message, unsigned int block_nb) {
uint32 w[64];
uint32 wv[8];
uint32 t1, t2;
......@@ -71,8 +71,7 @@ void Sha256::transform(const unsigned char *message, unsigned int block_nb)
wv[j] = m_h[j];
}
for (j = 0; j < 64; j++) {
t1 = wv[7] + Sha256_F2(wv[4]) + SHA2_CH(wv[4], wv[5], wv[6])
+ sha256_k[j] + w[j];
t1 = wv[7] + Sha256_F2(wv[4]) + SHA2_CH(wv[4], wv[5], wv[6]) + sha256_k[j] + w[j];
t2 = Sha256_F1(wv[0]) + SHA2_MAJ(wv[0], wv[1], wv[2]);
wv[7] = wv[6];
wv[6] = wv[5];
......@@ -89,6 +88,7 @@ void Sha256::transform(const unsigned char *message, unsigned int block_nb)
}
}
//------------------------------------------------------------------------------
void Sha256::init()
{
m_h[0] = 0x6a09e667;
......@@ -103,8 +103,8 @@ void Sha256::init()
m_tot_len = 0;
}
void Sha256::update(const unsigned char *message, unsigned int len)
{
//------------------------------------------------------------------------------
void Sha256::update(const unsigned char *message, unsigned int len) {
unsigned int block_nb;
unsigned int new_len, rem_len, tmp_len;
const unsigned char *shifted_message;
......@@ -126,21 +126,20 @@ void Sha256::update(const unsigned char *message, unsigned int len)
m_tot_len += (block_nb + 1) << 6;
}
void Sha256::finalResult(unsigned char *digest)
{
//------------------------------------------------------------------------------
void Sha256::finalResult(unsigned char *digest) {
unsigned int block_nb;
unsigned int pm_len;
unsigned int len_b;
int i;
block_nb = (1 + ((SHA224_256_BLOCK_SIZE - 9)
< (m_len % SHA224_256_BLOCK_SIZE)));
block_nb = (1 + ((SHA224_256_BLOCK_SIZE - 9) < (m_len % SHA224_256_BLOCK_SIZE)));
len_b = (m_tot_len + m_len) << 3;
pm_len = block_nb << 6;
memset(m_block + m_len, 0, pm_len - m_len);
m_block[m_len] = 0x80;
SHA2_UNPACK32(len_b, m_block + pm_len - 4);
transform(m_block, block_nb);
for (i = 0 ; i < 8; i++) {
for (i = 0; i < 8; i++) {
SHA2_UNPACK32(m_h[i], &digest[i << 2]);
}
}
......
......@@ -30,28 +30,27 @@
#define Sha256_H
#include <string>
class Sha256
{
protected:
class Sha256 {
protected:
typedef unsigned char uint8;
typedef unsigned int uint32;
typedef unsigned long long uint64;
const static uint32 sha256_k[];
static const unsigned int SHA224_256_BLOCK_SIZE = (512/8);
public:
static const unsigned int SHA224_256_BLOCK_SIZE = (512 / 8);
public:
Sha256();
~Sha256();
void init();
void update(const unsigned char *message, unsigned int len);
void finalResult(unsigned char *digest);
static const unsigned int DIGEST_SIZE = ( 256 / 8);
static const unsigned int DIGEST_SIZE = (256 / 8);
protected:
protected:
void transform(const unsigned char *message, unsigned int block_nb);
unsigned int m_tot_len;
unsigned int m_len;
unsigned char m_block[2*SHA224_256_BLOCK_SIZE];
unsigned char m_block[2 * SHA224_256_BLOCK_SIZE];
uint32 m_h[8];
};
......
......@@ -29,6 +29,7 @@
#include "nas_algorithms.hpp"
#include "logger.hpp"
//------------------------------------------------------------------------------
uint64_t MUL64x (uint64_t V, uint64_t c) {
if (V & 0x8000000000000000)
return (V << 1) ^ c;
......@@ -36,6 +37,7 @@ uint64_t MUL64x (uint64_t V, uint64_t c) {
return V << 1;
}
//------------------------------------------------------------------------------
uint64_t MUL64xPOW (uint64_t V, uint32_t i, uint64_t c){
if (i == 0)
return V;
......@@ -43,6 +45,7 @@ uint64_t MUL64xPOW (uint64_t V, uint32_t i, uint64_t c){
return MUL64x (MUL64xPOW (V, i - 1, c), c);
}
//------------------------------------------------------------------------------
uint64_t MUL64 (uint64_t V, uint64_t P, uint64_t c){
uint64_t result = 0;
int i = 0;
......@@ -53,6 +56,7 @@ uint64_t MUL64 (uint64_t V, uint64_t P, uint64_t c){
return result;
}
//------------------------------------------------------------------------------
uint32_t mask32bit (int n){
uint32_t mask = 0x0;
if (n % 32 == 0)
......@@ -62,7 +66,7 @@ uint32_t mask32bit (int n){
return mask;
}
//------------------------------------------------------------------------------
int nas_algorithms::nas_stream_encrypt_nea1(nas_stream_cipher_t * const stream_cipher, uint8_t * const out){
snow_3g_context_t snow_3g_context;
uint32_t *KS;
......@@ -108,6 +112,7 @@ int nas_algorithms::nas_stream_encrypt_nea1(nas_stream_cipher_t * const stream_c
return 0;
}
//------------------------------------------------------------------------------
int nas_algorithms::nas_stream_encrypt_nia1(nas_stream_cipher_t * const stream_cipher, uint8_t const out[4]){
snow_3g_context_t snow_3g_context;
uint32_t K[4], IV[4], z[5];
......@@ -166,6 +171,7 @@ int nas_algorithms::nas_stream_encrypt_nia1(nas_stream_cipher_t * const stream_c
return 0;
}
//------------------------------------------------------------------------------
int nas_algorithms::nas_stream_encrypt_nea2(nas_stream_cipher_t * const stream_cipher, uint8_t * const out){
uint8_t m[16];
uint32_t local_count;
......@@ -209,6 +215,7 @@ int nas_algorithms::nas_stream_encrypt_nea2(nas_stream_cipher_t * const stream_c
return 0;
}
//------------------------------------------------------------------------------
int nas_algorithms::nas_stream_encrypt_nia2(nas_stream_cipher_t * const stream_cipher, uint8_t const out[4]){
uint8_t *m = NULL;
uint32_t local_count = 0;
......
......@@ -44,7 +44,7 @@
#include <stdint.h>
#include <string.h>
#include <math.h>
extern "C"{
extern "C" {
#include "snow3g.h"
#include "conversions.h"
}
......@@ -70,7 +70,6 @@ extern "C"{
#define derive_key_up_int(aLGiD, kseaf, kNAS) \
Authentication_5gaka::derive_knas(UP_INT_ALG, aLGiD, kseaf, kNAS)
typedef struct {
uint8_t *key;
uint32_t key_length;
......@@ -82,29 +81,12 @@ typedef struct {
uint32_t blength;
} nas_stream_cipher_t;
class nas_algorithms{
public:
static int nas_stream_encrypt_nea1(nas_stream_cipher_t * const stream_cipher, uint8_t * const out);
static int nas_stream_encrypt_nia1(nas_stream_cipher_t * const stream_cipher, uint8_t const out[4]);
static int nas_stream_encrypt_nea2(nas_stream_cipher_t * const stream_cipher, uint8_t * const out);
static int nas_stream_encrypt_nia2(nas_stream_cipher_t * const stream_cipher, uint8_t const out[4]);
class nas_algorithms {
public:
static int nas_stream_encrypt_nea1(nas_stream_cipher_t *const stream_cipher, uint8_t *const out);
static int nas_stream_encrypt_nia1(nas_stream_cipher_t *const stream_cipher, uint8_t const out[4]);
static int nas_stream_encrypt_nea2(nas_stream_cipher_t *const stream_cipher, uint8_t *const out);
static int nas_stream_encrypt_nia2(nas_stream_cipher_t *const stream_cipher, uint8_t const out[4]);
};
#endif
......@@ -25,7 +25,6 @@
\email: contact@openairinterface.org
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
......@@ -34,50 +33,26 @@
#include "rijndael.h"
#include "snow3g.h"
static uint8_t _MULx (
uint8_t V,
uint8_t c);
static uint8_t _MULxPOW (
uint8_t V,
uint8_t i,
uint8_t c);
static uint32_t _MULalpha (
uint8_t c);
static uint32_t _DIValpha (
uint8_t c);
static uint32_t _S1 (
uint32_t w);
static uint32_t _S2 (
uint32_t w);
static void _snow3g_clock_LFSR_initialization_mode (
uint32_t F,
snow_3g_context_t * s3g_ctx_pP);
static void _snow3g_clock_LFSR_key_stream_mode (
snow_3g_context_t * snow_3g_context_pP);
static uint32_t _snow3g_clock_fsm (
snow_3g_context_t * snow_3g_context_pP);
void snow3g_initialize (
uint32_t k[4],
uint32_t IV[4],
snow_3g_context_t * snow_3g_context_pP);
void snow3g_generate_key_stream (
uint32_t n,
uint32_t * ks,
snow_3g_context_t * snow_3g_context_pP);
static uint8_t _MULx(uint8_t V, uint8_t c);
static uint8_t _MULxPOW(uint8_t V, uint8_t i, uint8_t c);
static uint32_t _MULalpha(uint8_t c);
static uint32_t _DIValpha(uint8_t c);
static uint32_t _S1(uint32_t w);
static uint32_t _S2(uint32_t w);
static void _snow3g_clock_LFSR_initialization_mode(uint32_t F, snow_3g_context_t *s3g_ctx_pP);
static void _snow3g_clock_LFSR_key_stream_mode(snow_3g_context_t *snow_3g_context_pP);
static uint32_t _snow3g_clock_fsm(snow_3g_context_t *snow_3g_context_pP);
void snow3g_initialize(uint32_t k[4], uint32_t IV[4], snow_3g_context_t *snow_3g_context_pP);
void snow3g_generate_key_stream(uint32_t n, uint32_t *ks, snow_3g_context_t *snow_3g_context_pP);
/* _MULx.
Input V: an 8-bit input.
Input c: an 8-bit input.
Output : an 8-bit input.
MULx maps 16 bits to 8 bits
*/
*/
static uint8_t
_MULx (
uint8_t V,
uint8_t c)
{
static uint8_t _MULx(uint8_t V, uint8_t c) {
//If the leftmost (i.e. the most significant) bit of V equals 1
if (V & 0x80)
return ((V << 1) ^ c);
......@@ -91,45 +66,33 @@ _MULx (
Input c: an 8-bit input.
Output : an 8-bit output.
MULxPOW maps 16 bits and a positive integer i to 8 bit.
*/
static uint8_t
_MULxPOW (
uint8_t V,
uint8_t i,
uint8_t c)
{
*/
static uint8_t _MULxPOW(uint8_t V, uint8_t i, uint8_t c) {
if (i == 0)
return V;
else
return _MULx (_MULxPOW (V, i - 1, c), c);
return _MULx(_MULxPOW(V, i - 1, c), c);
}
/* The function _MULalpha.
Input c: 8-bit input.
Output : 32-bit output.
maps 8 bits to 32 bits.
*/
*/
static uint32_t
_MULalpha (
uint8_t c)
{
return ((((uint32_t) _MULxPOW (c, 23, 0xa9)) << 24) | (((uint32_t) _MULxPOW (c, 245, 0xa9)) << 16) | (((uint32_t) _MULxPOW (c, 48, 0xa9)) << 8) | (((uint32_t) _MULxPOW (c, 239, 0xa9))));
static uint32_t _MULalpha(uint8_t c) {
return ((((uint32_t) _MULxPOW(c, 23, 0xa9)) << 24) | (((uint32_t) _MULxPOW(c, 245, 0xa9)) << 16) | (((uint32_t) _MULxPOW(c, 48, 0xa9)) << 8) | (((uint32_t) _MULxPOW(c, 239, 0xa9))));
}
/* The function DIV alpha.
Input c: 8-bit input.
Output : 32-bit output.
maps 8 bits to 32 bit.
*/
*/
static uint32_t
_DIValpha (
uint8_t c)
{
return ((((uint32_t) _MULxPOW (c, 16, 0xa9)) << 24) | (((uint32_t) _MULxPOW (c, 39, 0xa9)) << 16) | (((uint32_t) _MULxPOW (c, 6, 0xa9)) << 8) | (((uint32_t) _MULxPOW (c, 64, 0xa9))));
static uint32_t _DIValpha(uint8_t c) {
return ((((uint32_t) _MULxPOW(c, 16, 0xa9)) << 24) | (((uint32_t) _MULxPOW(c, 39, 0xa9)) << 16) | (((uint32_t) _MULxPOW(c, 6, 0xa9)) << 8) | (((uint32_t) _MULxPOW(c, 64, 0xa9))));
}
/* The 32x32-bit S-Box S1
......@@ -138,29 +101,19 @@ _DIValpha (
The S-Box S1 maps a 32-bit input to a 32-bit output.
w = w0 || w1 || w2 || w3 the 32-bit input with w0 the most and w3 the least significant byte.
S1(w)= r0 || r1 || r2 || r3 with r0 the most and r3 the least significant byte.
*/
static uint32_t
_S1 (
uint32_t w)
{
uint8_t r0 = 0,
r1 = 0,
r2 = 0,
r3 = 0;
uint8_t srw0 = SR[(uint8_t) ((w >> 24) & 0xff)];
uint8_t srw1 = SR[(uint8_t) ((w >> 16) & 0xff)];
uint8_t srw2 = SR[(uint8_t) ((w >> 8) & 0xff)];
uint8_t srw3 = SR[(uint8_t) ((w) & 0xff)];
r0 = ((_MULx (srw0, 0x1b)) ^ (srw1) ^ (srw2) ^ ((_MULx (srw3, 0x1b)) ^ srw3)
);
r1 = (((_MULx (srw0, 0x1b)) ^ srw0) ^ (_MULx (srw1, 0x1b)) ^ (srw2) ^ (srw3)
);
r2 = ((srw0) ^ ((_MULx (srw1, 0x1b)) ^ srw1) ^ (_MULx (srw2, 0x1b)) ^ (srw3)
);
r3 = ((srw0) ^ (srw1) ^ ((_MULx (srw2, 0x1b)) ^ srw2) ^ (_MULx (srw3, 0x1b))
);
*/
static uint32_t _S1(uint32_t w) {
uint8_t r0 = 0, r1 = 0, r2 = 0, r3 = 0;
uint8_t srw0 = SR[(uint8_t)((w >> 24) & 0xff)];
uint8_t srw1 = SR[(uint8_t)((w >> 16) & 0xff)];
uint8_t srw2 = SR[(uint8_t)((w >> 8) & 0xff)];
uint8_t srw3 = SR[(uint8_t)((w) & 0xff)];
r0 = ((_MULx(srw0, 0x1b)) ^ (srw1) ^ (srw2) ^ ((_MULx(srw3, 0x1b)) ^ srw3));
r1 = (((_MULx(srw0, 0x1b)) ^ srw0) ^ (_MULx(srw1, 0x1b)) ^ (srw2) ^ (srw3));
r2 = ((srw0) ^ ((_MULx(srw1, 0x1b)) ^ srw1) ^ (_MULx(srw2, 0x1b)) ^ (srw3));
r3 = ((srw0) ^ (srw1) ^ ((_MULx(srw2, 0x1b)) ^ srw2) ^ (_MULx(srw3, 0x1b)));
return ((((uint32_t) r0) << 24) | (((uint32_t) r1) << 16) | (((uint32_t) r2) << 8) | (((uint32_t) r3)));
}
......@@ -170,29 +123,19 @@ _S1 (
The S-Box S2 maps a 32-bit input to a 32-bit output.
Let w = w0 || w1 || w2 || w3 the 32-bit input with w0 the most and w3 the least significant byte.
Let S2(w)= r0 || r1 || r2 || r3 with r0 the most and r3 the least significant byte.
*/
static uint32_t
_S2 (
uint32_t w)
{
uint8_t r0 = 0,
r1 = 0,
r2 = 0,
r3 = 0;
uint8_t sqw0 = SQ[(uint8_t) ((w >> 24) & 0xff)];
uint8_t sqw1 = SQ[(uint8_t) ((w >> 16) & 0xff)];
uint8_t sqw2 = SQ[(uint8_t) ((w >> 8) & 0xff)];
uint8_t sqw3 = SQ[(uint8_t) ((w) & 0xff)];
r0 = ((_MULx (sqw0, 0x69)) ^ (sqw1) ^ (sqw2) ^ ((_MULx (sqw3, 0x69)) ^ sqw3)
);
r1 = (((_MULx (sqw0, 0x69)) ^ sqw0) ^ (_MULx (sqw1, 0x69)) ^ (sqw2) ^ (sqw3)
);
r2 = ((sqw0) ^ ((_MULx (sqw1, 0x69)) ^ sqw1) ^ (_MULx (sqw2, 0x69)) ^ (sqw3)
);
r3 = ((sqw0) ^ (sqw1) ^ ((_MULx (sqw2, 0x69)) ^ sqw2) ^ (_MULx (sqw3, 0x69))
);
*/
static uint32_t _S2(uint32_t w) {
uint8_t r0 = 0, r1 = 0, r2 = 0, r3 = 0;
uint8_t sqw0 = SQ[(uint8_t)((w >> 24) & 0xff)];
uint8_t sqw1 = SQ[(uint8_t)((w >> 16) & 0xff)];
uint8_t sqw2 = SQ[(uint8_t)((w >> 8) & 0xff)];
uint8_t sqw3 = SQ[(uint8_t)((w) & 0xff)];
r0 = ((_MULx(sqw0, 0x69)) ^ (sqw1) ^ (sqw2) ^ ((_MULx(sqw3, 0x69)) ^ sqw3));
r1 = (((_MULx(sqw0, 0x69)) ^ sqw0) ^ (_MULx(sqw1, 0x69)) ^ (sqw2) ^ (sqw3));
r2 = ((sqw0) ^ ((_MULx(sqw1, 0x69)) ^ sqw1) ^ (_MULx(sqw2, 0x69)) ^ (sqw3));
r3 = ((sqw0) ^ (sqw1) ^ ((_MULx(sqw2, 0x69)) ^ sqw2) ^ (_MULx(sqw3, 0x69)));
return ((((uint32_t) r0) << 24) | (((uint32_t) r1) << 16) | (((uint32_t) r2) << 8) | (((uint32_t) r3)));
}
......@@ -200,16 +143,10 @@ _S2 (
LFSR Registers S0 to S15 are updated as the LFSR receives a single clock.
Input F: a 32-bit word comes from output of FSM.
See section 3.4.4.
*/
*/
static void
_snow3g_clock_LFSR_initialization_mode (
uint32_t F,
snow_3g_context_t * s3g_ctx_pP)
{
uint32_t v = (((s3g_ctx_pP->LFSR_S0 << 8) & 0xffffff00) ^
(_MULalpha ((uint8_t) ((s3g_ctx_pP->LFSR_S0 >> 24) & 0xff))) ^ (s3g_ctx_pP->LFSR_S2) ^ ((s3g_ctx_pP->LFSR_S11 >> 8) & 0x00ffffff) ^ (_DIValpha ((uint8_t) ((s3g_ctx_pP->LFSR_S11) & 0xff))) ^ (F)
);
static void _snow3g_clock_LFSR_initialization_mode(uint32_t F, snow_3g_context_t *s3g_ctx_pP) {
uint32_t v = (((s3g_ctx_pP->LFSR_S0 << 8) & 0xffffff00) ^ (_MULalpha((uint8_t)((s3g_ctx_pP->LFSR_S0 >> 24) & 0xff))) ^ (s3g_ctx_pP->LFSR_S2) ^ ((s3g_ctx_pP->LFSR_S11 >> 8) & 0x00ffffff) ^ (_DIValpha((uint8_t)((s3g_ctx_pP->LFSR_S11) & 0xff))) ^ (F));
s3g_ctx_pP->LFSR_S0 = s3g_ctx_pP->LFSR_S1;
s3g_ctx_pP->LFSR_S1 = s3g_ctx_pP->LFSR_S2;
......@@ -232,15 +169,9 @@ _snow3g_clock_LFSR_initialization_mode (
/* Clocking LFSR in keystream mode.
LFSR Registers S0 to S15 are updated as the LFSR receives a single clock.
See section 3.4.5.
*/
static void
_snow3g_clock_LFSR_key_stream_mode (
snow_3g_context_t * snow_3g_context_pP)
{
uint32_t v = (((snow_3g_context_pP->LFSR_S0 << 8) & 0xffffff00) ^
(_MULalpha ((uint8_t) ((snow_3g_context_pP->LFSR_S0 >> 24) & 0xff))) ^
(snow_3g_context_pP->LFSR_S2) ^ ((snow_3g_context_pP->LFSR_S11 >> 8) & 0x00ffffff) ^ (_DIValpha ((uint8_t) ((snow_3g_context_pP->LFSR_S11) & 0xff)))
);
*/
static void _snow3g_clock_LFSR_key_stream_mode(snow_3g_context_t *snow_3g_context_pP) {
uint32_t v = (((snow_3g_context_pP->LFSR_S0 << 8) & 0xffffff00) ^ (_MULalpha((uint8_t)((snow_3g_context_pP->LFSR_S0 >> 24) & 0xff))) ^ (snow_3g_context_pP->LFSR_S2) ^ ((snow_3g_context_pP->LFSR_S11 >> 8) & 0x00ffffff) ^ (_DIValpha((uint8_t)((snow_3g_context_pP->LFSR_S11) & 0xff))));
snow_3g_context_pP->LFSR_S0 = snow_3g_context_pP->LFSR_S1;
snow_3g_context_pP->LFSR_S1 = snow_3g_context_pP->LFSR_S2;
......@@ -264,17 +195,14 @@ _snow3g_clock_LFSR_key_stream_mode (
Produces a 32-bit word F.
Updates FSM registers R1, R2, R3.
See Section 3.4.6.
*/
*/
static uint32_t
_snow3g_clock_fsm (
snow_3g_context_t * snow_3g_context_pP)
{
static uint32_t _snow3g_clock_fsm(snow_3g_context_t *snow_3g_context_pP) {
uint32_t F = ((snow_3g_context_pP->LFSR_S15 + snow_3g_context_pP->FSM_R1) & 0xffffffff) ^ snow_3g_context_pP->FSM_R2;
uint32_t r = (snow_3g_context_pP->FSM_R2 + (snow_3g_context_pP->FSM_R3 ^ snow_3g_context_pP->LFSR_S5)) & 0xffffffff;
snow_3g_context_pP->FSM_R3 = _S2 (snow_3g_context_pP->FSM_R2);
snow_3g_context_pP->FSM_R2 = _S1 (snow_3g_context_pP->FSM_R1);
snow_3g_context_pP->FSM_R3 = _S2(snow_3g_context_pP->FSM_R2);
snow_3g_context_pP->FSM_R2 = _S1(snow_3g_context_pP->FSM_R1);
snow_3g_context_pP->FSM_R1 = r;
return F;
}
......@@ -284,14 +212,9 @@ _snow3g_clock_fsm (
Input IV[4]: Four 32-bit words making 128-bit initialization variable.
Output: All the LFSRs and FSM are initialized for key generation.
See Section 4.1.
*/
void
snow3g_initialize (
uint32_t k[4],
uint32_t IV[4],
snow_3g_context_t * snow_3g_context_pP)
{
*/
void snow3g_initialize(uint32_t k[4], uint32_t IV[4], snow_3g_context_t *snow_3g_context_pP) {
uint8_t i = 0;
uint32_t F = 0x0;
......@@ -316,8 +239,8 @@ snow3g_initialize (
snow_3g_context_pP->FSM_R3 = 0x0;
for (i = 0; i < 32; i++) {
F = _snow3g_clock_fsm (snow_3g_context_pP);
_snow3g_clock_LFSR_initialization_mode (F, snow_3g_context_pP);
F = _snow3g_clock_fsm(snow_3g_context_pP);
_snow3g_clock_LFSR_initialization_mode(F, snow_3g_context_pP);
}
}
......@@ -327,26 +250,21 @@ snow3g_initialize (
memory is allocated already.
output: generated keystream which is filled in z
See section 4.2.
*/
void
snow3g_generate_key_stream (
uint32_t n,
uint32_t * ks,
snow_3g_context_t * snow_3g_context_pP)
{
*/
void snow3g_generate_key_stream(uint32_t n, uint32_t *ks, snow_3g_context_t *snow_3g_context_pP) {
uint32_t t = 0;
uint32_t F = 0x0;
_snow3g_clock_fsm (snow_3g_context_pP); /* Clock FSM once. Discard the output. */
_snow3g_clock_LFSR_key_stream_mode (snow_3g_context_pP); /* Clock LFSR in keystream mode once. */
_snow3g_clock_fsm(snow_3g_context_pP); /* Clock FSM once. Discard the output. */
_snow3g_clock_LFSR_key_stream_mode(snow_3g_context_pP); /* Clock LFSR in keystream mode once. */
for (t = 0; t < n; t++) {
F = _snow3g_clock_fsm (snow_3g_context_pP); /* STEP 1 */
F = _snow3g_clock_fsm(snow_3g_context_pP); /* STEP 1 */
ks[t] = F ^ snow_3g_context_pP->LFSR_S0; /* STEP 2 */
/*
* Note that ks[t] corresponds to z_{t+1} in section 4.2
*/
_snow3g_clock_LFSR_key_stream_mode (snow_3g_context_pP); /* STEP 3 */
_snow3g_clock_LFSR_key_stream_mode(snow_3g_context_pP); /* STEP 3 */
}
}
......@@ -20,16 +20,16 @@
*/
/*! \file snow3g.h
* \brief
* \author Open source Adapted from Specification of the 3GPP Confidentiality and
* Integrity Algorithms UEA2 & UIA2. Document 2: SNOW 3G Specification
* \integrators Kharbach Othmane, GAUTHIER Lionel.
* \date 2014
* \version
* \note
* \bug
* \warning
*/
* \brief
* \author Open source Adapted from Specification of the 3GPP Confidentiality and
* Integrity Algorithms UEA2 & UIA2. Document 2: SNOW 3G Specification
* \integrators Kharbach Othmane, GAUTHIER Lionel.
* \date 2014
* \version
* \note
* \bug
* \warning
*/
#ifndef FILE_SNOW3G_SEEN
#define FILE_SNOW3G_SEEN
......@@ -59,18 +59,18 @@ typedef struct snow_3g_context_s {
} snow_3g_context_t;
/* Initialization.
* Input k[4]: Four 32-bit words making up 128-bit key.
* Input IV[4]: Four 32-bit words making 128-bit initialization variable.
* Output: All the LFSRs and FSM are initialized for key generation.
*/
* Input k[4]: Four 32-bit words making up 128-bit key.
* Input IV[4]: Four 32-bit words making 128-bit initialization variable.
* Output: All the LFSRs and FSM are initialized for key generation.
*/
void snow3g_initialize(uint32_t k[4], uint32_t IV[4], snow_3g_context_t *snow_3g_context_pP);
/* Generation of Keystream.
* input n: number of 32-bit words of keystream.
* input z: space for the generated keystream, assumes
* memory is allocated already.
* output: generated keystream which is filled in z
*/
* input n: number of 32-bit words of keystream.
* input z: space for the generated keystream, assumes
* memory is allocated already.
* output: generated keystream which is filled in z
*/
void snow3g_generate_key_stream(uint32_t n, uint32_t *z, snow_3g_context_t *snow_3g_context_pP);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment