refactor PR#55's peer list implementation to utilize a lookup table; add support to peer list implementation, when in whitelist mode to support per peer passwords (techincally this works in blacklist mode but is ... well irrelevant as blacklist mode *rejects* connections from peers in the list file); correct a few issues regarding how NAKs are returned early in the authentication handshake; reformat log messages; fix issue in host voice when regular conventional traffic is sent to a DVRS-enabled channel and legacy group grant is disabled;

3.6-maint
Bryan Biedenkapp 2 years ago
parent 7a6ec842d3
commit f39e8de0e1

@ -1,3 +1,6 @@
# Example blacklist or whitelist
1234
12345
#
# This file sets the valid peer IDs allowed on a FNE.
#
# Entry Format: "PeerID,Peer Password,<newline>"
#1234,
#5678,MYSECUREPASSWORD,

@ -1,5 +1,6 @@
#
# This file sets the valid Radio IDs allowed on a repeater.
#
# RID,Enabled (1 = Enabled / 0 = Disabled),Optional Alias,<newline>
# Entry Format: "RID,Enabled (1 = Enabled / 0 = Disabled),Optional Alias,<newline>"
#
#1234,1,RID Alias,

@ -9,7 +9,7 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
*
* Copyright (C) 2016 Jonathan Naylor, G4KLX
* Copyright (C) 2017-2022 Bryan Biedenkapp, N2PLL
* Copyright (C) 2017-2022,2024 Bryan Biedenkapp, N2PLL
* Copyright (c) 2024 Patrick McDonnell, W3AXL
* Copyright (c) 2024 Caleb, KO4UYJ
*
@ -35,42 +35,43 @@ std::mutex PeerListLookup::m_mutex;
/// <summary>
/// Initializes a new instance of the PeerListLookup class.
/// </summary>
/// <param name="listFile">Full-path to the list file.</param>
/// <param name="filename">Full-path to the list file.</param>
/// <param name="mode">Mode to operate in (WHITELIST or BLACKLIST).</param>
/// <param name="enabled">Flag indicating if the lookup is enabled.</param>
PeerListLookup::PeerListLookup(const std::string& listFile, Mode mode, uint32_t reloadTime, bool enabled)
: LookupTable(listFile, reloadTime), m_mode(mode), m_enabled(enabled)
/// <param name="peerAcl">Flag indicating if the lookup is enabled.</param>
PeerListLookup::PeerListLookup(const std::string& filename, Mode mode, uint32_t reloadTime, bool peerAcl) : LookupTable(filename, reloadTime),
m_acl(peerAcl), m_mode(mode)
{
/* stub */
}
/// <summary>
/// Get the list of peers in the table.
/// </summary>
std::vector<uint32_t> PeerListLookup::getPeerList() const
{
std::lock_guard<std::mutex> lock(m_mutex);
return m_list;
}
/// <summary>
/// Clears all entries from the list.
/// </summary>
void PeerListLookup::clear()
{
std::lock_guard<std::mutex> lock(m_mutex);
m_list.clear();
m_table.clear();
}
/// <summary>
/// Adds a new entry to the list.
/// </summary>
/// <param name="peerId">Unique peer ID to add.</param>
void PeerListLookup::addEntry(uint32_t peerId)
/// <param name="password"></param>
void PeerListLookup::addEntry(uint32_t id, const std::string& password)
{
PeerId entry = PeerId(id, password, false);
std::lock_guard<std::mutex> lock(m_mutex);
if (std::find(m_list.begin(), m_list.end(), peerId) == m_list.end()) {
m_list.push_back(peerId);
try {
PeerId _entry = m_table.at(id);
// if either the alias or the enabled flag doesn't match, update the entry
if (_entry.peerId() == id) {
_entry = PeerId(id, password, false);
m_table[id] = _entry;
}
} catch (...) {
m_table[id] = entry;
}
}
@ -78,55 +79,89 @@ void PeerListLookup::addEntry(uint32_t peerId)
/// Removes an existing entry from the list.
/// </summary>
/// <param name="peerId">Unique peer ID to remove.</param>
void PeerListLookup::removeEntry(uint32_t peerId)
void PeerListLookup::eraseEntry(uint32_t id)
{
std::lock_guard<std::mutex> lock(m_mutex);
try {
m_table.at(id);
m_table.erase(id);
} catch (...) {
/* stub */
}
}
/// <summary>
/// Finds a table entry in this lookup table.
/// </summary>
/// <param name="id">Unique identifier for table entry.</param>
/// <returns>Table entry.</returns>
PeerId PeerListLookup::find(uint32_t id)
{
PeerId entry;
std::lock_guard<std::mutex> lock(m_mutex);
m_list.erase(std::remove(m_list.begin(), m_list.end(), peerId), m_list.end());
try {
entry = m_table.at(id);
} catch (...) {
entry = PeerId(0U, "", true);
}
return entry;
}
/// <summary>
/// Commit the table.
/// </summary>
/// <param name="mode">The mode to set.</param>
void PeerListLookup::commit()
{
save();
}
/// <summary>
/// Gets whether the lookup is enabled.
/// </summary>
bool PeerListLookup::getACL() const
{
return m_acl;
}
/// <summary>
/// Checks if a peer ID is in the list.
/// </summary>
/// <param name="peerId">Unique peer ID to check.</param>
/// <param name="id">Unique peer ID to check.</param>
/// <returns>True if the peer ID is in the list, otherwise false.</returns>
bool PeerListLookup::isPeerInList(uint32_t peerId) const
bool PeerListLookup::isPeerInList(uint32_t id) const
{
std::lock_guard<std::mutex> lock(m_mutex);
bool found = std::find(m_list.begin(), m_list.end(), peerId) != m_list.end();
if (m_table.find(id) != m_table.end()) {
return true;
}
return found;
return false;
}
/// <summary>
/// Checks if a peer ID is allowed based on the mode and enabled flag.
/// </summary>
/// <param name="peerId">Unique peer ID to check.</param>
/// <param name="id">Unique peer ID to check.</param>
/// <returns>True if the peer ID is allowed, otherwise false.</returns>
bool PeerListLookup::isPeerAllowed(uint32_t peerId) const
bool PeerListLookup::isPeerAllowed(uint32_t id) const
{
if (!m_enabled) {
if (!m_acl) {
return true; // if not enabled, allow all peers
}
bool allowed = false;
if (m_mode == WHITELIST) {
allowed = isPeerInList(peerId);
allowed = isPeerInList(id);
} else if (m_mode == BLACKLIST) {
allowed = !isPeerInList(peerId);
allowed = !isPeerInList(id);
}
return allowed;
}
/// <summary>
/// Commit the table.
/// </summary>
/// <param name="mode">The mode to set.</param>
void PeerListLookup::commit()
{
save();
}
/// <summary>
/// Sets the mode to either WHITELIST or BLACKLIST.
/// </summary>
@ -145,39 +180,6 @@ PeerListLookup::Mode PeerListLookup::getMode() const
return m_mode;
}
/// <summary>
/// Sets whether the lookup is enabled.
/// </summary>
/// <param name="enabled">Flag indicating if the lookup is enabled.</param>
void PeerListLookup::setEnabled(bool enabled)
{
std::lock_guard<std::mutex> lock(m_mutex);
m_enabled = enabled;
}
/// <summary>
/// Gets whether the lookup is enabled.
/// </summary>
bool PeerListLookup::getEnabled() const
{
return m_enabled;
}
/// <summary>
/// Finds a table entry in this lookup table.
/// </summary>
/// <param name="id">Unique identifier for table entry.</param>
/// <returns>Table entry.</returns>
uint32_t PeerListLookup::find(uint32_t id)
{
std::lock_guard<std::mutex> lock(m_mutex);
if (isPeerInList(id)) {
return id;
} else {
return 0;
}
}
// ---------------------------------------------------------------------------
// Private Class Members
// ---------------------------------------------------------------------------
@ -198,28 +200,57 @@ bool PeerListLookup::load()
return false;
}
m_list.clear();
m_table.clear();
std::lock_guard<std::mutex> lock(m_mutex);
// read lines from file
std::string line;
while (std::getline(file, line)) {
if (line.length() > 0) {
if (line.at(0) == '#') {
// Skip comments with #
if (line.at(0) == '#')
continue;
// tokenize line
std::string next;
std::vector<std::string> parsed;
char delim = ',';
for (char c : line) {
if (c == delim) {
if (!next.empty()) {
parsed.push_back(next);
next.clear();
}
}
else
next += c;
}
if (!next.empty())
parsed.push_back(next);
// parse tokenized line
uint32_t id = ::atoi(parsed[0].c_str());
uint32_t peerId = ::strtoul(line.c_str(), nullptr, 10);
if (peerId != 0) {
m_list.push_back(peerId);
LogDebug(LOG_HOST, "Loaded peer ID %u into peer lookup table", peerId);
// Check for an optional alias field
if (parsed.size() >= 2) {
m_table[id] = PeerId(id, parsed[1], false);
LogDebug(LOG_HOST, "Loaded peer ID %u into peer ID lookup table, using unique peer password", id);
} else {
m_table[id] = PeerId(id, "", false);
LogDebug(LOG_HOST, "Loaded peer ID %u into peer ID lookup table, using master password", id);
}
}
}
file.close();
LogInfoEx(LOG_HOST, "Loaded %lu peers into list", m_list.size());
return !m_list.empty();
size_t size = m_table.size();
if (size == 0U)
return false;
LogInfoEx(LOG_HOST, "Loaded %lu peers into list", size);
return true;
}
/// <summary>
@ -240,14 +271,39 @@ bool PeerListLookup::save()
return false;
}
// Counter for lines written
unsigned int lines = 0;
std::lock_guard<std::mutex> lock(m_mutex);
for (auto& peerId : m_list) {
file << peerId << "\n";
// String for writing
std::string line;
// iterate over each entry in the RID lookup and write it to the open file
for (auto& entry: m_table) {
// Get the parameters
uint32_t peerId = entry.first;
std::string password = entry.second.peerPassword();
// Format into a string
line = std::to_string(peerId) + ",";
// Add the alias if we have one
if (password.length() > 0) {
line += password;
line += ",";
}
// Add the newline
line += "\n";
// Write to file
file << line;
// Increment
lines++;
}
file.close();
LogInfoEx(LOG_HOST, "Saved %lu peers to list", m_list.size());
if (lines != m_table.size())
return false;
LogInfoEx(LOG_HOST, "Saved %u entries to lookup table file %s", lines, m_filename.c_str());
return true;
}

@ -9,7 +9,7 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
*
* Copyright (C) 2016 Jonathan Naylor, G4KLX
* Copyright (C) 2017-2022 Bryan Biedenkapp, N2PLL
* Copyright (C) 2017-2022,2024 Bryan Biedenkapp, N2PLL
* Copyright (c) 2024 Patrick McDonnell, W3AXL
* Copyright (c) 2024 Caleb, KO4UYJ
*
@ -28,11 +28,70 @@ namespace lookups
{
// ---------------------------------------------------------------------------
// Class Declaration
// Implements a threading lookup table class that contains peer whitelist
// and blacklist.
// Represents an individual entry in the peer ID table.
// ---------------------------------------------------------------------------
class HOST_SW_API PeerListLookup : public LookupTable<uint32_t> {
class HOST_SW_API PeerId {
public:
/// <summary>Initializes a new instance of the PeerId class.</summary>
PeerId() :
m_peerId(0U),
m_peerPassword(),
m_peerDefault(false)
{
/* stub */
}
/// <summary>Initializes a new instance of the PeerId class.</summary>
/// <param name="peerId"></param>
/// <param name="peerPassword"></param>
/// <param name="peerDefault"></param>
PeerId(uint32_t peerId, const std::string& peerPassword, bool peerDefault) :
m_peerId(peerId),
m_peerPassword(peerPassword),
m_peerDefault(peerDefault)
{
/* stub */
}
/// <summary>Equals operator. Copies this PeerId to another PeerId.</summary>
PeerId& operator=(const PeerId& data)
{
if (this != &data) {
m_peerId = data.m_peerId;
m_peerPassword = data.m_peerPassword;
m_peerDefault = data.m_peerDefault;
}
return *this;
}
/// <summary>Sets flag values.</summary>
/// <param name="peerId">Peer ID.</param>
/// <param name="peerPassword">Per Peer Password.</param>
/// <param name="peerDefault"></param>
void set(uint32_t peerId, const std::string& peerPassword, bool peerDefault)
{
m_peerId = peerId;
m_peerPassword = peerPassword;
m_peerDefault = peerDefault;
}
public:
/// <summary>Peer ID.</summary>
__READONLY_PROPERTY_PLAIN(uint32_t, peerId);
/// <summary>Per Peer Password.</summary>
__READONLY_PROPERTY_PLAIN(std::string, peerPassword);
/// <summary>Flag indicating if the peer is default.</summary>
__READONLY_PROPERTY_PLAIN(bool, peerDefault);
};
// ---------------------------------------------------------------------------
// Class Declaration
// Implements a threading lookup table class that contains peer ID
// lookup table.
// ---------------------------------------------------------------------------
class HOST_SW_API PeerListLookup : public LookupTable<PeerId> {
public:
enum Mode {
WHITELIST,
@ -40,57 +99,49 @@ namespace lookups
};
/// <summary>Initializes a new instance of the PeerListLookup class.</summary>
PeerListLookup(const std::string& listFile, Mode mode, uint32_t reloadTime, bool enabled);
/// <sumary>Get the list of peers in the table.</summary>
std::vector<uint32_t> getPeerList() const;
PeerListLookup(const std::string& filename, Mode mode, uint32_t reloadTime, bool peerAcl);
/// <summary>Clears all entries from the list.</summary>
void clear() override;
/// <summary>Adds a new entry to the list.</summary>
void addEntry(uint32_t peerId);
void addEntry(uint32_t id, const std::string& password = "");
/// <summary>Removes an existing entry from the list.</summary>
void removeEntry(uint32_t peerId);
/// <summary>Checks if a peer ID is in the list.</summary>
bool isPeerInList(uint32_t peerId) const;
/// <summary>Checks if a peer ID is allowed based on the mode and enabled flag.</summary>
bool isPeerAllowed(uint32_t peerId) const;
void eraseEntry(uint32_t id);
/// <summary>Finds a table entry in this lookup table.</summary>
PeerId find(uint32_t id) override;
/// <summary>Commit the table.</summary>
void commit();
/// <summary>Gets whether the lookup is enabled.</summary>
bool getACL() const;
/// <summary>Checks if a peer ID is in the list.</summary>
bool isPeerInList(uint32_t id) const;
/// <summary>Checks if a peer ID is allowed based on the mode and enabled flag.</summary>
bool isPeerAllowed(uint32_t id) const;
/// <summary>Sets the mode to either WHITELIST or BLACKLIST.</summary>
void setMode(Mode mode);
/// <summary>Gets the current mode.</summary>
Mode getMode() const;
/// <summary>Sets whether the lookup is enabled.</summary>
void setEnabled(bool enabled);
/// <summary>Gets whether the lookup is enabled.</summary>
bool getEnabled() const;
/// <summary>Finds a table entry in this lookup table.</summary>
uint32_t find(uint32_t id) override;
protected:
bool m_acl;
/// <summary>Loads the table from the passed lookup table file.</summary>
/// <returns>True, if lookup table was loaded, otherwise false.</returns>
bool load() override;
/// <summary>Saves the table to the passed lookup table file.</summary>
/// <returns>True, if lookup table was saved, otherwise false.</returns>
bool save() override;
private:
std::string m_listFile;
Mode m_mode;
bool m_enabled;
std::vector<uint32_t> m_list;
static std::mutex m_mutex;
bool loadList();
bool saveList() const;
static std::mutex m_mutex;
};
} // namespace lookups

@ -206,14 +206,13 @@ bool RadioIdLookup::load()
// parse tokenized line
uint32_t id = ::atoi(parsed[0].c_str());
bool radioEnabled = ::atoi(parsed[1].c_str()) == 1;
bool radioDefault = false;
// Check for an optional alias field
if (parsed.size() >= 3) {
m_table[id] = RadioId(radioEnabled, radioDefault, parsed[2]);
m_table[id] = RadioId(radioEnabled, false, parsed[2]);
LogDebug(LOG_HOST, "Loaded RID %u (%s) into RID lookup table", id, parsed[2].c_str());
} else {
m_table[id] = RadioId(radioEnabled, radioDefault);
m_table[id] = RadioId(radioEnabled, false);
LogDebug(LOG_HOST, "Loaded RID %u into RID lookup table", id);
}
}

@ -122,7 +122,6 @@ namespace lookups
/// <summary>Adds a new entry to the lookup table by the specified unique ID, with an alias.</summary>
void addEntry(uint32_t id, bool enabled, const std::string& alias);
/// <summary>Erases an existing entry from the lookup table by the specified unique ID.</summary>
void eraseEntry(uint32_t id);
/// <summary>Finds a table entry in this lookup table.</summary>

@ -624,11 +624,38 @@ void* FNENetwork::threadedNetworkRx(void* arg)
::memset(salt, 0x00U, 4U);
__SET_UINT32(connection->salt(), salt, 0U);
size_t size = network->m_password.size();
std::string passwordForPeer = network->m_password;
// check if the peer is in the peer ACL list
bool validAcl = true;
if (network->m_peerListLookup->getACL()) {
if (!network->m_peerListLookup->isPeerAllowed(peerId)) {
if (network->m_peerListLookup->getMode() == lookups::PeerListLookup::BLACKLIST) {
LogWarning(LOG_NET, "PEER %u RPTK, blacklisted from access", peerId);
} else {
LogWarning(LOG_NET, "PEER %u RPTK, failed whitelist check", peerId);
}
validAcl = false;
} else {
lookups::PeerId peerEntry = network->m_peerListLookup->find(peerId);
if (peerEntry.peerDefault()) {
validAcl = false; // default peer IDs are a no-no as they have no data thus fail ACL check
} else {
passwordForPeer = peerEntry.peerPassword();
if (passwordForPeer.length() == 0) {
passwordForPeer = network->m_password;
}
}
}
}
if (validAcl) {
size_t size = passwordForPeer.size();
uint8_t* in = new uint8_t[size + sizeof(uint32_t)];
::memcpy(in, salt, sizeof(uint32_t));
for (size_t i = 0U; i < size; i++)
in[i + sizeof(uint32_t)] = network->m_password.at(i);
in[i + sizeof(uint32_t)] = passwordForPeer.at(i);
uint8_t out[32U];
edac::SHA256 sha256;
@ -648,39 +675,25 @@ void* FNENetwork::threadedNetworkRx(void* arg)
}
}
// check if the peer is (not)whitelisted or blacklisted
bool validAcl = true;
if (!network->m_peerListLookup->isPeerAllowed(peerId)) {
if (network->m_peerListLookup->getMode() == lookups::PeerListLookup::BLACKLIST) {
LogWarning(LOG_NET, "PEER %u is blacklisted", peerId);
} else {
LogWarning(LOG_NET, "PEER %u is not whitelisted", peerId);
}
validAcl = false;
}
if (validHash && validAcl) {
if (validHash) {
connection->connectionState(NET_STAT_WAITING_CONFIG);
network->writePeerACK(peerId);
LogInfoEx(LOG_NET, "PEER %u RPTK ACK, completed the login exchange", peerId);
network->m_peers[peerId] = connection;
}
else {
LogWarning(LOG_NET, "PEER %u RPTK NAK, failed the login exchange", peerId);
if (!validAcl) {
network->writePeerNAK(peerId, TAG_REPEATER_AUTH, NET_CONN_NAK_PEER_ACL);
} else {
network->writePeerNAK(peerId, TAG_REPEATER_AUTH, NET_CONN_NAK_FNE_UNAUTHORIZED);
network->writePeerNAK(peerId, TAG_REPEATER_AUTH, NET_CONN_NAK_FNE_UNAUTHORIZED, req->address, req->addrLen);
network->erasePeer(peerId);
}
} else {
network->writePeerNAK(peerId, TAG_REPEATER_AUTH, NET_CONN_NAK_PEER_ACL, req->address, req->addrLen);
network->erasePeer(peerId);
}
network->m_peers[peerId] = connection;
}
else {
LogWarning(LOG_NET, "PEER %u RPTK NAK, login exchange while in an incorrect state, connectionState = %u", peerId, connection->connectionState());
network->writePeerNAK(peerId, TAG_REPEATER_AUTH, NET_CONN_NAK_BAD_CONN_STATE);
network->writePeerNAK(peerId, TAG_REPEATER_AUTH, NET_CONN_NAK_BAD_CONN_STATE, req->address, req->addrLen);
network->erasePeer(peerId);
}
}
@ -709,14 +722,14 @@ void* FNENetwork::threadedNetworkRx(void* arg)
std::string err = json::parse(v, payload);
if (!err.empty()) {
LogWarning(LOG_NET, "PEER %u RPTC NAK, supplied invalid configuration data", peerId);
network->writePeerNAK(peerId, TAG_REPEATER_AUTH, NET_CONN_NAK_INVALID_CONFIG_DATA);
network->writePeerNAK(peerId, TAG_REPEATER_AUTH, NET_CONN_NAK_INVALID_CONFIG_DATA, req->address, req->addrLen);
network->erasePeer(peerId);
}
else {
// ensure parsed JSON is an object
if (!v.is<json::object>()) {
LogWarning(LOG_NET, "PEER %u RPTC NAK, supplied invalid configuration data", peerId);
network->writePeerNAK(peerId, TAG_REPEATER_AUTH, NET_CONN_NAK_INVALID_CONFIG_DATA);
network->writePeerNAK(peerId, TAG_REPEATER_AUTH, NET_CONN_NAK_INVALID_CONFIG_DATA, req->address, req->addrLen);
network->erasePeer(peerId);
}
else {
@ -780,7 +793,7 @@ void* FNENetwork::threadedNetworkRx(void* arg)
else {
LogWarning(LOG_NET, "PEER %u (%s) RPTC NAK, login exchange while in an incorrect state, connectionState = %u", peerId, connection->identity().c_str(),
connection->connectionState());
network->writePeerNAK(peerId, TAG_REPEATER_CONFIG, NET_CONN_NAK_BAD_CONN_STATE);
network->writePeerNAK(peerId, TAG_REPEATER_CONFIG, NET_CONN_NAK_BAD_CONN_STATE, req->address, req->addrLen);
network->erasePeer(peerId);
}
}
@ -1777,7 +1790,7 @@ void FNENetwork::logPeerNAKReason(uint32_t peerId, const char* tag, NET_CONN_NAK
LogWarning(LOG_NET, "PEER %u NAK %s, reason = %u; FNE demanded connection reset", peerId, tag, (uint16_t)reason);
break;
case NET_CONN_NAK_PEER_ACL:
LogWarning(LOG_NET, "PEER %u NAK %s, reason = %u; ACL Rejection", peerId, tag, (uint16_t)reason);
LogWarning(LOG_NET, "PEER %u NAK %s, reason = %u; ACL rejection", peerId, tag, (uint16_t)reason);
break;
case NET_CONN_NAK_GENERAL_FAILURE:

@ -1215,12 +1215,17 @@ void RESTAPI::restAPI_GetPeerList(const HTTPPayload& request, HTTPPayload& reply
json::array peers = json::array();
if (m_peerListLookup != nullptr) {
for (const auto& peerId : m_peerListLookup->getPeerList()) {
if (m_peerListLookup->table().size() > 0) {
for (auto entry : m_peerListLookup->table()) {
json::object peerObj = json::object();
uint32_t peerId = entry.first;
peerObj["peerId"].set<uint32_t>(peerId);
peers.push_back(json::value(peerObj));
}
}
}
response["peers"].set<json::array>(peers);
reply.payload(response);
@ -1281,7 +1286,7 @@ void RESTAPI::restAPI_PutPeerDelete(const HTTPPayload& request, HTTPPayload& rep
uint32_t peerId = req["peerId"].get<uint32_t>();
m_peerListLookup->removeEntry(peerId);
m_peerListLookup->eraseEntry(peerId);
}
/// <summary>
@ -1320,11 +1325,11 @@ void RESTAPI::restAPI_GetPeerMode(const HTTPPayload& request, HTTPPayload& reply
setResponseDefaultStatus(response);
lookups::PeerListLookup::Mode mode = m_peerListLookup->getMode();
bool enabled = m_peerListLookup->getEnabled();
bool acl = m_peerListLookup->getACL();
std::string modeStr;
if (enabled) {
if (acl) {
switch (mode) {
case lookups::PeerListLookup::WHITELIST:
modeStr = "WHITELIST";

@ -545,7 +545,7 @@ void Network::clock(uint32_t ms)
LogWarning(LOG_NET, "PEER %u master NAK; FNE demanded connection reset, remotePeerId = %u", m_peerId, rtpHeader.getSSRC());
break;
case NET_CONN_NAK_PEER_ACL:
LogWarning(LOG_NET, "PEER %u master NAK; ACL Rejection, remotePeerId = %u", m_peerId, rtpHeader.getSSRC());
LogWarning(LOG_NET, "PEER %u master NAK; ACL rejection, remotePeerId = %u", m_peerId, rtpHeader.getSSRC());
break;
case NET_CONN_NAK_GENERAL_FAILURE:

@ -391,6 +391,11 @@ bool Voice::process(uint8_t* data, uint32_t len)
if (m_p25->m_legacyGroupReg && group) {
if (!m_p25->m_affiliations.isGroupAff(srcId, dstId)) {
if (!m_p25->m_control->writeRF_TSDU_Grp_Aff_Rsp(srcId, dstId)) {
LogWarning(LOG_RF, P25_HDU_STR " denial, conventional affiliation required, not affiliated to TGID, srcId = %u, dstId = %u", srcId, dstId);
m_p25->m_rfLastDstId = 0U;
m_p25->m_rfLastSrcId = 0U;
m_p25->m_rfTGHang.stop();
m_p25->m_rfState = RS_RF_REJECTED;
return false;
}
}
@ -401,6 +406,11 @@ bool Voice::process(uint8_t* data, uint32_t len)
}
}
else {
LogWarning(LOG_RF, P25_HDU_STR " denial, conventional affiliation required, and legacy group grant disabled, not affiliated to TGID, srcId = %u, dstId = %u", srcId, dstId);
m_p25->m_rfLastDstId = 0U;
m_p25->m_rfLastSrcId = 0U;
m_p25->m_rfTGHang.stop();
m_p25->m_rfState = RS_RF_REJECTED;
return false;
}
}

Loading…
Cancel
Save

Powered by TurnKey Linux.