diff --git a/src/ccallsign.cpp b/src/ccallsign.cpp index 29fc27c..410a0c0 100644 --- a/src/ccallsign.cpp +++ b/src/ccallsign.cpp @@ -203,11 +203,27 @@ void CCallsign::GetSuffix(uint8 *buffer) const //////////////////////////////////////////////////////////////////////////////////////// // compare + bool CCallsign::HasSameCallsign(const CCallsign &Callsign) const { return (::memcmp(m_Callsign, Callsign.m_Callsign, sizeof(m_Callsign)) == 0); } +bool CCallsign::HasSameCallsignWithWidlcard(const CCallsign &callsign) const +{ + bool same = true; + bool done = false; + + for ( int i = 0; (i < sizeof(m_Callsign)) && same && !done; i++ ) + { + if ( !(done = ((m_Callsign[i] == '*') || (callsign[i] == '*'))) ) + { + same &= (m_Callsign[i] == callsign[i]); + } + } + return same; +} + bool CCallsign::HasSameModule(const CCallsign &Callsign) const { return (m_Module == Callsign.m_Module); diff --git a/src/ccallsign.h b/src/ccallsign.h index 51de462..07c9f69 100644 --- a/src/ccallsign.h +++ b/src/ccallsign.h @@ -69,8 +69,9 @@ public: // compare bool HasSameCallsign(const CCallsign &) const; + bool HasSameCallsignWithWidlcard(const CCallsign &) const; bool HasSameModule(const CCallsign &) const; - + // operators bool operator ==(const CCallsign &) const; operator const char *() const; diff --git a/src/ccallsignlist.cpp b/src/ccallsignlist.cpp new file mode 100644 index 0000000..eafa18a --- /dev/null +++ b/src/ccallsignlist.cpp @@ -0,0 +1,153 @@ +// +// ccallsignlist.cpp +// xlxd +// +// Created by Jean-Luc Deltombe (LX3JL) on 30/12/2015. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of xlxd. +// +// xlxd is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// xlxd is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#include +#include +#include +#include "main.h" +#include "ccallsignlist.h" + +//////////////////////////////////////////////////////////////////////////////////////// +// constructor + +CCallsignList::CCallsignList() +{ + m_Filename = NULL; + ::memset(&m_LastModTime, 0, sizeof(CCallsignList)); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// destructor + +CCallsignList::~CCallsignList() +{ + if ( m_Filename != NULL ) + { + delete m_Filename; + } +} + + + +//////////////////////////////////////////////////////////////////////////////////////// +// file io + +bool CCallsignList::LoadFromFile(const char *filename) +{ + bool ok = false; + char sz[CALLSIGN_LEN+1]; + + // and load + std::ifstream file (filename); + if ( file.is_open() ) + { + Lock(); + + // empty list + clear(); + // fill with file content + while ( file.getline(sz, sizeof(sz)).good() ) + { + push_back(CCallsign(sz)); + } + // close file + file.close(); + + // keep file path + m_Filename = filename; + + // update time + GetLastModTime(&m_LastModTime); + + // and done + Unlock(); + ok = true; + std::cout << "Gatekeeper loaded " << size() << " lines from " << filename << std::endl; + } + else + { + std::cout << "Gatekeeper cannot find " << filename << std::endl; + } + + return ok; +} + +bool CCallsignList::ReloadFromFile(void) +{ + bool ok = false; + + if ( m_Filename != NULL ) + { + ok = LoadFromFile(m_Filename); + } + return ok; +} + +bool CCallsignList::NeedReload(void) +{ + bool needReload = false; + + time_t time; + if ( GetLastModTime(&time) ) + { + needReload = time != m_LastModTime; + } + return needReload; +} + +bool CCallsignList::GetLastModTime(time_t *time) +{ + bool ok = false; + + if ( m_Filename != NULL ) + { + int file=0; + if( (file = ::open(m_Filename, O_RDONLY)) != -1 ) + { + struct stat fileStat; + if( ::fstat(file, &fileStat) != -1 ) + { + *time = fileStat.st_mtime; + ok = true; + } + } + + } + return ok; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// compare + +bool CCallsignList::IsListed(const CCallsign &callsign) const +{ + bool listed = false; + + for ( int i = 0; (i < size()) && !listed; i++ ) + { + listed = (data()[i]).HasSameCallsignWithWidlcard(callsign); + } + + return listed; +} diff --git a/src/ccallsignlist.h b/src/ccallsignlist.h new file mode 100644 index 0000000..5f9496e --- /dev/null +++ b/src/ccallsignlist.h @@ -0,0 +1,69 @@ +// +// ccallsignlist.h +// xlxd +// +// Created by Jean-Luc Deltombe (LX3JL) on 30/12/2015. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of xlxd. +// +// xlxd is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// xlxd is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Foobar. If not, see . +// ---------------------------------------------------------------------------- + + +#ifndef ccallsignlist_h +#define ccallsignlist_h + +#include "main.h" +#include "ccallsign.h" + +//////////////////////////////////////////////////////////////////////////////////////// +// class + +class CCallsignList : public std::vector +{ +public: + // constructor + CCallsignList(); + + // destructor + virtual ~CCallsignList(); + + // locks + void Lock(void) { m_Mutex.lock(); } + void Unlock(void) { m_Mutex.unlock(); } + + // file io + bool LoadFromFile(const char *); + bool ReloadFromFile(void); + bool NeedReload(void); + + // compare + bool IsListed(const CCallsign &) const; + +protected: + // + bool GetLastModTime(time_t *); + +protected: + // data + std::mutex m_Mutex; + const char * m_Filename; + time_t m_LastModTime; +}; + + +//////////////////////////////////////////////////////////////////////////////////////// +#endif /* ccallsignlist_h */ diff --git a/src/cgatekeeper.cpp b/src/cgatekeeper.cpp index 614d489..345bd5e 100644 --- a/src/cgatekeeper.cpp +++ b/src/cgatekeeper.cpp @@ -22,6 +22,161 @@ // along with Foobar. If not, see . // ---------------------------------------------------------------------------- +#include "main.h" +#include "ctimepoint.h" #include "cgatekeeper.h" +//////////////////////////////////////////////////////////////////////////////////////// + CGateKeeper g_GateKeeper; + + +//////////////////////////////////////////////////////////////////////////////////////// +// constructor + +CGateKeeper::CGateKeeper() +{ + m_bStopThread = false; + m_pThread = NULL; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// destructor + +CGateKeeper::~CGateKeeper() +{ + // kill threads + m_bStopThread = true; + if ( m_pThread != NULL ) + { + m_pThread->join(); + delete m_pThread; + } +} + + +//////////////////////////////////////////////////////////////////////////////////////// +// init & clode + +bool CGateKeeper::Init(void) +{ + + // load lists from files + m_WhiteList.LoadFromFile(WHITELIST_PATH); + m_BlackList.LoadFromFile(BLACKLIST_PATH); + + // reset stop flag + m_bStopThread = false; + + // start thread; + m_pThread = new std::thread(CGateKeeper::Thread, this); + + return true; +} + +void CGateKeeper::Close(void) +{ + m_bStopThread = true; + if ( m_pThread != NULL ) + { + m_pThread->join(); + delete m_pThread; + m_pThread = NULL; + } +} + +//////////////////////////////////////////////////////////////////////////////////////// +// operation + +bool CGateKeeper::MayLink(const CCallsign &callsign, const CIp &ip, int protocol) const +{ + bool ok = true; + + // first check is IP & callsigned listed OK + ok &= IsListedOk(callsign, ip); + + // then apply any protocol specific authorisation for the operation + + // report + if ( !ok ) + { + std::cout << "Gatekeeper blocking linking of " << callsign << " @ " << ip << " using protocol " << protocol << std::endl; + } + + // done + return ok; +} + +bool CGateKeeper::MayTransmit(const CCallsign &callsign, const CIp &ip, int protocol) const +{ + bool ok = true; + + // first check is IP & callsigned listed OK + ok &= IsListedOk(callsign, ip); + + // then apply any protocol specific authorisation for the operation + + // report + if ( !ok ) + { + std::cout << "Gatekeeper blocking transmiting of " << callsign << " @ " << ip << " using protocol " << protocol << std::endl; + } + + // done + return ok; +} + + +//////////////////////////////////////////////////////////////////////////////////////// +// thread + +void CGateKeeper::Thread(CGateKeeper *This) +{ + while ( !This->m_bStopThread ) + { + // Wait 30 seconds + CTimePoint::TaskSleepFor(30000); + + // have lists files changed ? + if ( This->m_WhiteList.NeedReload() ) + { + This->m_WhiteList.ReloadFromFile(); + } + if ( This->m_BlackList.NeedReload() ) + { + This->m_BlackList.ReloadFromFile(); + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////// +// operation helpers + +bool CGateKeeper::IsListedOk(const CCallsign &callsign, const CIp &ip) const +{ + bool ok = true; + + // first check IP + + // next, check callsign + if ( ok ) + { + // first check if callsign is in white list + // note if white list is empty, everybody is authorized + const_cast(m_WhiteList).Lock(); + if ( !m_WhiteList.empty() ) + { + ok = m_WhiteList.IsListed(callsign); + } + const_cast(m_WhiteList).Unlock(); + + // then check if not blacklisted + const_cast(m_BlackList).Lock(); + ok &= !m_BlackList.IsListed(callsign); + const_cast(m_BlackList).Unlock(); + } + + // done + return ok; + +} diff --git a/src/cgatekeeper.h b/src/cgatekeeper.h index dee78b3..b6bff36 100644 --- a/src/cgatekeeper.h +++ b/src/cgatekeeper.h @@ -28,6 +28,7 @@ #include "main.h" #include "ccallsign.h" #include "cip.h" +#include "ccallsignlist.h" //////////////////////////////////////////////////////////////////////////////////////// // class @@ -36,14 +37,34 @@ class CGateKeeper { public: // constructor - CGateKeeper() {} + CGateKeeper(); // destructor - ~CGateKeeper() {} + virtual ~CGateKeeper(); + + // init & clode + bool Init(void); + void Close(void); // operation - bool MayLink(const CCallsign &, const CIp &, int) { return true; } - bool MayTransmit(const CCallsign &, const CIp &, int) { return true; } + bool MayLink(const CCallsign &, const CIp &, int) const; + bool MayTransmit(const CCallsign &, const CIp &, int) const; + +protected: + // thread + static void Thread(CGateKeeper *); + + // operation helpers + bool IsListedOk(const CCallsign &, const CIp &) const; + +protected: + // data + CCallsignList m_WhiteList; + CCallsignList m_BlackList; + + // thread + bool m_bStopThread; + std::thread *m_pThread; }; diff --git a/src/cprotocol.cpp b/src/cprotocol.cpp index 403b09b..04cadff 100644 --- a/src/cprotocol.cpp +++ b/src/cprotocol.cpp @@ -97,7 +97,6 @@ void CProtocol::Close(void) void CProtocol::Thread(CProtocol *This) { - while ( !This->m_bStopThread ) { This->Task(); diff --git a/src/creflector.cpp b/src/creflector.cpp index ab52e4a..7ae773f 100644 --- a/src/creflector.cpp +++ b/src/creflector.cpp @@ -25,6 +25,7 @@ #include "main.h" #include #include "creflector.h" +#include "cgatekeeper.h" //////////////////////////////////////////////////////////////////////////////////////// @@ -90,6 +91,9 @@ bool CReflector::Start(void) // reset stop flag m_bStopThreads = false; + // init gate keeper + ok &= g_GateKeeper.Init(); + // create protocols ok &= m_Protocols.Init(); @@ -138,6 +142,12 @@ void CReflector::Stop(void) m_RouterThreads[i] = NULL; } } + + // close protocols + m_Protocols.Close(); + + // close gatekeeper + g_GateKeeper.Close(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -322,7 +332,7 @@ void CReflector::XmlReportThread(CReflector *This) { // report to xml file std::ofstream xmlFile; - xmlFile.open("/var/log/xlxd.xml", std::ios::out | std::ios::trunc); + xmlFile.open(XML_PATH, std::ios::out | std::ios::trunc); if ( xmlFile.is_open() ) { // write xml file diff --git a/src/main.cpp b/src/main.cpp index 308a171..f629b66 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -42,7 +42,7 @@ CReflector g_Reflector; int main(int argc, const char * argv[]) { #ifdef RUN_AS_DAEMON - + // redirect cout, cerr and clog to syslog syslog::redirect cout_redir(std::cout); syslog::redirect cerr_redir(std::cerr); @@ -83,7 +83,7 @@ int main(int argc, const char * argv[]) close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); - + #endif // check arguments diff --git a/src/main.h b/src/main.h index cca6c75..0c2bf79 100644 --- a/src/main.h +++ b/src/main.h @@ -47,7 +47,7 @@ // version ----------------------------------------------------- #define VERSION_MAJOR 1 -#define VERSION_MINOR 0 +#define VERSION_MINOR 1 #define VERSION_REVISION 0 // global ------------------------------------------------------ @@ -81,7 +81,7 @@ // DCS #define DCS_PORT 30051 // UDP port #define DCS_KEEPALIVE_PERIOD 1 // in seconds -#define DCS_KEEPALIVE_TIMEOUT (DCS_KEEPALIVE_PERIOD*10) // in seconds +#define DCS_KEEPALIVE_TIMEOUT (DCS_KEEPALIVE_PERIOD*30) // in seconds // xml & json reporting ----------------------------------------- @@ -90,6 +90,12 @@ #define JSON_UPDATE_PERIOD 10 // in seconds #define JSON_PORT 10001 +// system paths ------------------------------------------------- + +#define XML_PATH "/var/log/xlxd.xml" +#define WHITELIST_PATH "/xlxd/xlxd.whitelist" +#define BLACKLIST_PATH "/xlxd/xlxd.blacklist" + //////////////////////////////////////////////////////////////////////////////////////// // typedefs