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