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 <string.h>
#include <sys/stat.h>
#include "cg3client.h"
#include "cg3protocol.h"
#include "creflector.h"
@ -40,6 +41,8 @@ bool CG3Protocol::Init(void)
{
bool ok;
ReadOptions();
// base class
ok = CProtocol::Init();
@ -260,6 +263,7 @@ void CG3Protocol::ConfigTask(void)
}
else
{
std::cout << "Module " << Call << " invalid" << std::endl;
Buffer.data()[3] = 0x01; // reject
}
}
@ -269,10 +273,19 @@ void CG3Protocol::ConfigTask(void)
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
Buffer.resize(8);
Buffer.Append((uint8 *)(const char *)Call, CALLSIGN_LEN - 1);
Buffer.Append((uint8)Call.GetModule());
Buffer.Append((uint8)module);
// RPT1
Buffer.Append((uint8 *)(const char *)GetReflectorCallsign(), CALLSIGN_LEN - 1);
@ -293,7 +306,16 @@ void CG3Protocol::ConfigTask(void)
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
{
@ -400,14 +422,14 @@ void CG3Protocol::Task(void)
if ( (Frame = IsValidDvFramePacket(Buffer)) != NULL )
{
//std::cout << "Terminal DV frame" << std::endl;
// handle it
OnDvFramePacketIn(Frame, BaseIp);
}
else if ( (Header = IsValidDvHeaderPacket(Buffer)) != NULL )
{
//std::cout << "Terminal DV header" << std::endl;
// callsign muted?
if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, PROTOCOL_G3, Header->GetRpt2Module()) )
{
@ -452,6 +474,9 @@ void CG3Protocol::Task(void)
// update time
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())
{
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
@ -724,3 +760,105 @@ bool CG3Protocol::EncodeDvLastFramePacket(const CDvLastFramePacket &Packet, CBuf
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
#define cg3protocol_h
#include <string>
#include "ctimepoint.h"
#include "cprotocol.h"
#include "cdvheaderpacket.h"
@ -59,7 +60,7 @@ class CG3Protocol : public CProtocol
{
public:
// constructor
CG3Protocol() {};
CG3Protocol() : m_GwAddress(0u), m_Modules("*"), m_LastModTime(0) {};
// destructor
virtual ~CG3Protocol() {};
@ -84,6 +85,13 @@ protected:
void ConfigTask(void);
void IcmpTask(void);
// config
void ReadOptions(void);
// helper
char *TrimWhiteSpaces(char *);
bool NeedReload(void);
// queue helper
void HandleQueue(void);
@ -97,12 +105,12 @@ protected:
CDvHeaderPacket *IsValidDvHeaderPacket(const CBuffer &);
CDvFramePacket *IsValidDvFramePacket(const CBuffer &);
CDvLastFramePacket *IsValidDvLastFramePacket(const CBuffer &);
// packet encoding helpers
bool EncodeDvHeaderPacket(const CDvHeaderPacket &, CBuffer *) const;
bool EncodeDvFramePacket(const CDvFramePacket &, CBuffer *) const;
bool EncodeDvLastFramePacket(const CDvLastFramePacket &, CBuffer *) const;
protected:
std::thread *m_pPresenceThread;
std::thread *m_pConfigThread;
@ -116,6 +124,11 @@ protected:
CUdpSocket m_PresenceSocket;
CUdpSocket m_ConfigSocket;
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 BLACKLIST_PATH "/xlxd/xlxd.blacklist"
#define INTERLINKLIST_PATH "/xlxd/xlxd.interlink"
#define TERMINALOPTIONS_PATH "/xlxd/xlxd.terminal"
#define DEBUGDUMP_PATH "/var/log/xlxd.debug"
// system constants ---------------------------------------------

Loading…
Cancel
Save

Powered by TurnKey Linux.