Added terminal option file

2 options for now
- external IP adress to be used for rhe routing information
- restrict modules
pull/127/head
Marius Petrescu, YO2LOJ 7 years ago
parent d070e96121
commit f4f78bc4f2

@ -0,0 +1,17 @@
#########################################################################################
# XLXD terminal option file
#
# one line per entry
# each entry specifies a terminal option
#
# Valid option:
# address <ip> - Ip address to be used by the terminal route responder
# By default, the request destination address is used.
# If the system is behind a router, set it to the public IP
# If the system runs on the public IP, leave unset.
# modules <modules> - a string with all modules to accept a terminal connection
# Default value is "*", meaning accept all
#
#########################################################################################
#address 193.1.2.3
#modules BCD

@ -24,6 +24,7 @@
#include "main.h" #include "main.h"
#include <string.h> #include <string.h>
#include <sys/stat.h>
#include "cg3client.h" #include "cg3client.h"
#include "cg3protocol.h" #include "cg3protocol.h"
#include "creflector.h" #include "creflector.h"
@ -40,6 +41,8 @@ bool CG3Protocol::Init(void)
{ {
bool ok; bool ok;
ReadOptions();
// base class // base class
ok = CProtocol::Init(); ok = CProtocol::Init();
@ -260,6 +263,7 @@ void CG3Protocol::ConfigTask(void)
} }
else else
{ {
std::cout << "Module " << Call << " invalid" << std::endl;
Buffer.data()[3] = 0x01; // reject Buffer.data()[3] = 0x01; // reject
} }
} }
@ -269,10 +273,19 @@ void CG3Protocol::ConfigTask(void)
Buffer.data()[3] = 0x01; // reject Buffer.data()[3] = 0x01; // reject
} }
char module = Call.GetModule();
if (!strchr(m_Modules.c_str(), module) && !strchr(m_Modules.c_str(), '*'))
{
// restricted
std::cout << "Module " << Call << " restricted by configuration" << std::endl;
Buffer.data()[3] = 0x01; // reject
}
// UR // UR
Buffer.resize(8); Buffer.resize(8);
Buffer.Append((uint8 *)(const char *)Call, CALLSIGN_LEN - 1); Buffer.Append((uint8 *)(const char *)Call, CALLSIGN_LEN - 1);
Buffer.Append((uint8)Call.GetModule()); Buffer.Append((uint8)module);
// RPT1 // RPT1
Buffer.Append((uint8 *)(const char *)GetReflectorCallsign(), CALLSIGN_LEN - 1); Buffer.Append((uint8 *)(const char *)GetReflectorCallsign(), CALLSIGN_LEN - 1);
@ -293,7 +306,16 @@ void CG3Protocol::ConfigTask(void)
if (Buffer.data()[3] == 0x00) if (Buffer.data()[3] == 0x00)
{ {
Buffer.Append(*(uint32 *)m_ConfigSocket.GetLocalAddr()); std::cout << "External G3 gateway address " << inet_ntoa(*(in_addr *)&m_GwAddress) << std::endl;
if (m_GwAddress == 0)
{
Buffer.Append(*(uint32 *)m_ConfigSocket.GetLocalAddr());
}
else
{
Buffer.Append(m_GwAddress);
}
} }
else else
{ {
@ -400,14 +422,14 @@ void CG3Protocol::Task(void)
if ( (Frame = IsValidDvFramePacket(Buffer)) != NULL ) if ( (Frame = IsValidDvFramePacket(Buffer)) != NULL )
{ {
//std::cout << "Terminal DV frame" << std::endl; //std::cout << "Terminal DV frame" << std::endl;
// handle it // handle it
OnDvFramePacketIn(Frame, BaseIp); OnDvFramePacketIn(Frame, BaseIp);
} }
else if ( (Header = IsValidDvHeaderPacket(Buffer)) != NULL ) else if ( (Header = IsValidDvHeaderPacket(Buffer)) != NULL )
{ {
//std::cout << "Terminal DV header" << std::endl; //std::cout << "Terminal DV header" << std::endl;
// callsign muted? // callsign muted?
if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, PROTOCOL_G3, Header->GetRpt2Module()) ) if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, PROTOCOL_G3, Header->GetRpt2Module()) )
{ {
@ -452,6 +474,9 @@ void CG3Protocol::Task(void)
// update time // update time
m_LastKeepaliveTime.Now(); m_LastKeepaliveTime.Now();
// reload option if needed
NeedReload();
} }
} }
@ -566,7 +591,18 @@ bool CG3Protocol::OnDvHeaderPacketIn(CDvHeaderPacket *Header, const CIp &Ip)
{ {
if (client->GetReflectorModule() != Header->GetRpt2Callsign().GetModule()) if (client->GetReflectorModule() != Header->GetRpt2Callsign().GetModule())
{ {
client->SetReflectorModule(Header->GetRpt2Callsign().GetModule()); char new_module = Header->GetRpt2Callsign().GetModule();
if (strchr(m_Modules.c_str(), '*') || strchr(m_Modules.c_str(), new_module))
{
client->SetReflectorModule(new_module);
}
else
{
// drop if invalid module
delete Header;
g_Reflector.ReleaseClients();
return NULL;
}
} }
// get client callsign // get client callsign
@ -724,3 +760,105 @@ bool CG3Protocol::EncodeDvLastFramePacket(const CDvLastFramePacket &Packet, CBuf
return true; return true;
} }
////////////////////////////////////////////////////////////////////////////////////////
// option helpers
char *CG3Protocol::TrimWhiteSpaces(char *str)
{
char *end;
while ((*str == ' ') || (*str == '\t')) str++;
if (*str == 0)
return str;
end = str + strlen(str) - 1;
while ((end > str) && ((*end == ' ') || (*end == '\t') || (*end == '\r'))) end --;
*(end + 1) = 0;
return str;
}
bool CG3Protocol::NeedReload(void)
{
struct stat fileStat;
if (::stat(TERMINALOPTIONS_PATH, &fileStat) != -1)
{
if (m_LastModTime != fileStat.st_mtime)
{
ReadOptions();
}
}
// iterate on clients
CClients *clients = g_Reflector.GetClients();
int index = -1;
CClient *client = NULL;
while ( (client = clients->FindNextClient(PROTOCOL_G3, &index)) != NULL )
{
char module = client->GetReflectorModule();
if (!strchr(m_Modules.c_str(), module) && !strchr(m_Modules.c_str(), '*'))
{
clients->RemoveClient(client);
}
}
g_Reflector.ReleaseClients();
}
void CG3Protocol::ReadOptions(void)
{
char sz[256];
int opts = 0;
std::ifstream file(TERMINALOPTIONS_PATH);
if (file.is_open())
{
m_GwAddress = 0u;
m_Modules = "*";
while (file.getline(sz, sizeof(sz)).good())
{
char *szt = TrimWhiteSpaces(sz);
char *szval;
if ((::strlen(szt) > 0) && szt[0] != '#')
{
if ((szt = ::strtok(szt, " ,\t")) != NULL)
{
if ((szval = ::strtok(NULL, " ,\t")) != NULL)
{
if (::strncmp(szt, "address", 7) == 0)
{
in_addr addr = { .s_addr = inet_addr(szval) };
if (addr.s_addr)
{
std::cout << "G3 handler address set to " << inet_ntoa(addr) << std::endl;
m_GwAddress = addr.s_addr;
opts++;
}
}
else if (strncmp(szt, "modules", 7) == 0)
{
std::cout << "G3 handler module list set to " << szval << std::endl;
m_Modules = szval;
opts++;
}
else
{
// unknown option - ignore
}
}
}
}
}
std::cout << "G3 handler loaded " << opts << " options from file " << TERMINALOPTIONS_PATH << std::endl;
file.close();
struct stat fileStat;
if (::stat(TERMINALOPTIONS_PATH, &fileStat) != -1)
{
m_LastModTime = fileStat.st_mtime;
}
}
}

@ -25,6 +25,7 @@
#ifndef cg3protocol_h #ifndef cg3protocol_h
#define cg3protocol_h #define cg3protocol_h
#include <string>
#include "ctimepoint.h" #include "ctimepoint.h"
#include "cprotocol.h" #include "cprotocol.h"
#include "cdvheaderpacket.h" #include "cdvheaderpacket.h"
@ -59,7 +60,7 @@ class CG3Protocol : public CProtocol
{ {
public: public:
// constructor // constructor
CG3Protocol() {}; CG3Protocol() : m_GwAddress(0u), m_Modules("*"), m_LastModTime(0) {};
// destructor // destructor
virtual ~CG3Protocol() {}; virtual ~CG3Protocol() {};
@ -84,6 +85,13 @@ protected:
void ConfigTask(void); void ConfigTask(void);
void IcmpTask(void); void IcmpTask(void);
// config
void ReadOptions(void);
// helper
char *TrimWhiteSpaces(char *);
bool NeedReload(void);
// queue helper // queue helper
void HandleQueue(void); void HandleQueue(void);
@ -97,12 +105,12 @@ protected:
CDvHeaderPacket *IsValidDvHeaderPacket(const CBuffer &); CDvHeaderPacket *IsValidDvHeaderPacket(const CBuffer &);
CDvFramePacket *IsValidDvFramePacket(const CBuffer &); CDvFramePacket *IsValidDvFramePacket(const CBuffer &);
CDvLastFramePacket *IsValidDvLastFramePacket(const CBuffer &); CDvLastFramePacket *IsValidDvLastFramePacket(const CBuffer &);
// packet encoding helpers // packet encoding helpers
bool EncodeDvHeaderPacket(const CDvHeaderPacket &, CBuffer *) const; bool EncodeDvHeaderPacket(const CDvHeaderPacket &, CBuffer *) const;
bool EncodeDvFramePacket(const CDvFramePacket &, CBuffer *) const; bool EncodeDvFramePacket(const CDvFramePacket &, CBuffer *) const;
bool EncodeDvLastFramePacket(const CDvLastFramePacket &, CBuffer *) const; bool EncodeDvLastFramePacket(const CDvLastFramePacket &, CBuffer *) const;
protected: protected:
std::thread *m_pPresenceThread; std::thread *m_pPresenceThread;
std::thread *m_pConfigThread; std::thread *m_pConfigThread;
@ -116,6 +124,11 @@ protected:
CUdpSocket m_PresenceSocket; CUdpSocket m_PresenceSocket;
CUdpSocket m_ConfigSocket; CUdpSocket m_ConfigSocket;
int m_IcmpRawSocket; int m_IcmpRawSocket;
// optional params
uint32 m_GwAddress;
std::string m_Modules;
time_t m_LastModTime;
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

@ -153,6 +153,7 @@
#define WHITELIST_PATH "/xlxd/xlxd.whitelist" #define WHITELIST_PATH "/xlxd/xlxd.whitelist"
#define BLACKLIST_PATH "/xlxd/xlxd.blacklist" #define BLACKLIST_PATH "/xlxd/xlxd.blacklist"
#define INTERLINKLIST_PATH "/xlxd/xlxd.interlink" #define INTERLINKLIST_PATH "/xlxd/xlxd.interlink"
#define TERMINALOPTIONS_PATH "/xlxd/xlxd.terminal"
#define DEBUGDUMP_PATH "/var/log/xlxd.debug" #define DEBUGDUMP_PATH "/var/log/xlxd.debug"
// system constants --------------------------------------------- // system constants ---------------------------------------------

Loading…
Cancel
Save

Powered by TurnKey Linux.