From f39e8de0e1a94883e3ff167242f056af8cf97c7c Mon Sep 17 00:00:00 2001 From: Bryan Biedenkapp Date: Sat, 15 Jun 2024 08:26:51 -0400 Subject: [PATCH] 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; --- configs/peer_list.example.dat | 9 +- configs/rid_acl.example.dat | 3 +- src/common/lookups/PeerListLookup.cpp | 222 ++++++++++++++++---------- src/common/lookups/PeerListLookup.h | 117 ++++++++++---- src/common/lookups/RadioIdLookup.cpp | 5 +- src/common/lookups/RadioIdLookup.h | 1 - src/fne/network/FNENetwork.cpp | 109 +++++++------ src/fne/network/RESTAPI.cpp | 19 ++- src/host/network/Network.cpp | 2 +- src/host/p25/packet/Voice.cpp | 10 ++ 10 files changed, 317 insertions(+), 180 deletions(-) diff --git a/configs/peer_list.example.dat b/configs/peer_list.example.dat index c522fb8e..0b96ea4a 100644 --- a/configs/peer_list.example.dat +++ b/configs/peer_list.example.dat @@ -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," +#1234, +#5678,MYSECUREPASSWORD, diff --git a/configs/rid_acl.example.dat b/configs/rid_acl.example.dat index c3941a69..b26ad5f5 100644 --- a/configs/rid_acl.example.dat +++ b/configs/rid_acl.example.dat @@ -1,5 +1,6 @@ # # This file sets the valid Radio IDs allowed on a repeater. # -# RID,Enabled (1 = Enabled / 0 = Disabled),Optional Alias, +# Entry Format: "RID,Enabled (1 = Enabled / 0 = Disabled),Optional Alias," +# #1234,1,RID Alias, diff --git a/src/common/lookups/PeerListLookup.cpp b/src/common/lookups/PeerListLookup.cpp index 5200d598..c27159ef 100644 --- a/src/common/lookups/PeerListLookup.cpp +++ b/src/common/lookups/PeerListLookup.cpp @@ -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; /// /// Initializes a new instance of the PeerListLookup class. /// -/// Full-path to the list file. +/// Full-path to the list file. /// Mode to operate in (WHITELIST or BLACKLIST). -/// Flag indicating if the lookup is enabled. -PeerListLookup::PeerListLookup(const std::string& listFile, Mode mode, uint32_t reloadTime, bool enabled) - : LookupTable(listFile, reloadTime), m_mode(mode), m_enabled(enabled) +/// Flag indicating if the lookup is enabled. +PeerListLookup::PeerListLookup(const std::string& filename, Mode mode, uint32_t reloadTime, bool peerAcl) : LookupTable(filename, reloadTime), + m_acl(peerAcl), m_mode(mode) { /* stub */ } -/// -/// Get the list of peers in the table. -/// -std::vector PeerListLookup::getPeerList() const -{ - std::lock_guard lock(m_mutex); - return m_list; -} - /// /// Clears all entries from the list. /// void PeerListLookup::clear() { std::lock_guard lock(m_mutex); - m_list.clear(); + m_table.clear(); } /// /// Adds a new entry to the list. /// /// Unique peer ID to add. -void PeerListLookup::addEntry(uint32_t peerId) +/// +void PeerListLookup::addEntry(uint32_t id, const std::string& password) { + PeerId entry = PeerId(id, password, false); + std::lock_guard 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. /// /// Unique peer ID to remove. -void PeerListLookup::removeEntry(uint32_t peerId) +void PeerListLookup::eraseEntry(uint32_t id) +{ + std::lock_guard lock(m_mutex); + try { + m_table.at(id); + m_table.erase(id); + } catch (...) { + /* stub */ + } +} + +/// +/// Finds a table entry in this lookup table. +/// +/// Unique identifier for table entry. +/// Table entry. +PeerId PeerListLookup::find(uint32_t id) { + PeerId entry; + std::lock_guard 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; +} + +/// +/// Commit the table. +/// +/// The mode to set. +void PeerListLookup::commit() +{ + save(); +} + +/// +/// Gets whether the lookup is enabled. +/// +bool PeerListLookup::getACL() const +{ + return m_acl; } /// /// Checks if a peer ID is in the list. /// -/// Unique peer ID to check. +/// Unique peer ID to check. /// True if the peer ID is in the list, otherwise false. -bool PeerListLookup::isPeerInList(uint32_t peerId) const +bool PeerListLookup::isPeerInList(uint32_t id) const { std::lock_guard 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; } /// /// Checks if a peer ID is allowed based on the mode and enabled flag. /// -/// Unique peer ID to check. +/// Unique peer ID to check. /// True if the peer ID is allowed, otherwise false. -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; } -/// -/// Commit the table. -/// -/// The mode to set. -void PeerListLookup::commit() -{ - save(); -} - /// /// Sets the mode to either WHITELIST or BLACKLIST. /// @@ -145,39 +180,6 @@ PeerListLookup::Mode PeerListLookup::getMode() const return m_mode; } -/// -/// Sets whether the lookup is enabled. -/// -/// Flag indicating if the lookup is enabled. -void PeerListLookup::setEnabled(bool enabled) -{ - std::lock_guard lock(m_mutex); - m_enabled = enabled; -} - -/// -/// Gets whether the lookup is enabled. -/// -bool PeerListLookup::getEnabled() const -{ - return m_enabled; -} - -/// -/// Finds a table entry in this lookup table. -/// -/// Unique identifier for table entry. -/// Table entry. -uint32_t PeerListLookup::find(uint32_t id) -{ - std::lock_guard 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 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; - } - 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); + // tokenize line + std::string next; + std::vector 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()); + + // 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; } /// @@ -240,14 +271,39 @@ bool PeerListLookup::save() return false; } + // Counter for lines written + unsigned int lines = 0; + std::lock_guard 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; } \ No newline at end of file diff --git a/src/common/lookups/PeerListLookup.h b/src/common/lookups/PeerListLookup.h index f324d2bf..4d664bf0 100644 --- a/src/common/lookups/PeerListLookup.h +++ b/src/common/lookups/PeerListLookup.h @@ -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 { + class HOST_SW_API PeerId { + public: + /// Initializes a new instance of the PeerId class. + PeerId() : + m_peerId(0U), + m_peerPassword(), + m_peerDefault(false) + { + /* stub */ + } + /// Initializes a new instance of the PeerId class. + /// + /// + /// + PeerId(uint32_t peerId, const std::string& peerPassword, bool peerDefault) : + m_peerId(peerId), + m_peerPassword(peerPassword), + m_peerDefault(peerDefault) + { + /* stub */ + } + + /// Equals operator. Copies this PeerId to another PeerId. + 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; + } + + /// Sets flag values. + /// Peer ID. + /// Per Peer Password. + /// + void set(uint32_t peerId, const std::string& peerPassword, bool peerDefault) + { + m_peerId = peerId; + m_peerPassword = peerPassword; + m_peerDefault = peerDefault; + } + + public: + /// Peer ID. + __READONLY_PROPERTY_PLAIN(uint32_t, peerId); + /// Per Peer Password. + __READONLY_PROPERTY_PLAIN(std::string, peerPassword); + /// Flag indicating if the peer is default. + __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 { public: enum Mode { WHITELIST, @@ -40,57 +99,49 @@ namespace lookups }; /// Initializes a new instance of the PeerListLookup class. - PeerListLookup(const std::string& listFile, Mode mode, uint32_t reloadTime, bool enabled); - - /// Get the list of peers in the table. - std::vector getPeerList() const; + PeerListLookup(const std::string& filename, Mode mode, uint32_t reloadTime, bool peerAcl); /// Clears all entries from the list. void clear() override; /// Adds a new entry to the list. - void addEntry(uint32_t peerId); - + void addEntry(uint32_t id, const std::string& password = ""); /// Removes an existing entry from the list. - void removeEntry(uint32_t peerId); - - /// Checks if a peer ID is in the list. - bool isPeerInList(uint32_t peerId) const; - - /// Checks if a peer ID is allowed based on the mode and enabled flag. - bool isPeerAllowed(uint32_t peerId) const; + void eraseEntry(uint32_t id); + /// Finds a table entry in this lookup table. + PeerId find(uint32_t id) override; /// Commit the table. void commit(); + /// Gets whether the lookup is enabled. + bool getACL() const; + + /// Checks if a peer ID is in the list. + bool isPeerInList(uint32_t id) const; + /// Checks if a peer ID is allowed based on the mode and enabled flag. + bool isPeerAllowed(uint32_t id) const; + /// Sets the mode to either WHITELIST or BLACKLIST. void setMode(Mode mode); - /// Gets the current mode. Mode getMode() const; - /// Sets whether the lookup is enabled. - void setEnabled(bool enabled); - - /// Gets whether the lookup is enabled. - bool getEnabled() const; - - /// Finds a table entry in this lookup table. - uint32_t find(uint32_t id) override; - protected: + bool m_acl; + + /// Loads the table from the passed lookup table file. + /// True, if lookup table was loaded, otherwise false. bool load() override; + + /// Saves the table to the passed lookup table file. + /// True, if lookup table was saved, otherwise false. bool save() override; private: - std::string m_listFile; Mode m_mode; - bool m_enabled; - std::vector m_list; - static std::mutex m_mutex; - bool loadList(); - bool saveList() const; + static std::mutex m_mutex; }; } // namespace lookups diff --git a/src/common/lookups/RadioIdLookup.cpp b/src/common/lookups/RadioIdLookup.cpp index 42c0557b..aee6961b 100644 --- a/src/common/lookups/RadioIdLookup.cpp +++ b/src/common/lookups/RadioIdLookup.cpp @@ -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); } } diff --git a/src/common/lookups/RadioIdLookup.h b/src/common/lookups/RadioIdLookup.h index 3c207962..9e95f914 100644 --- a/src/common/lookups/RadioIdLookup.h +++ b/src/common/lookups/RadioIdLookup.h @@ -122,7 +122,6 @@ namespace lookups /// Adds a new entry to the lookup table by the specified unique ID, with an alias. void addEntry(uint32_t id, bool enabled, const std::string& alias); - /// Erases an existing entry from the lookup table by the specified unique ID. void eraseEntry(uint32_t id); /// Finds a table entry in this lookup table. diff --git a/src/fne/network/FNENetwork.cpp b/src/fne/network/FNENetwork.cpp index 5b4771fd..9d854cb9 100644 --- a/src/fne/network/FNENetwork.cpp +++ b/src/fne/network/FNENetwork.cpp @@ -624,63 +624,76 @@ void* FNENetwork::threadedNetworkRx(void* arg) ::memset(salt, 0x00U, 4U); __SET_UINT32(connection->salt(), salt, 0U); - size_t size = network->m_password.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); - - uint8_t out[32U]; - edac::SHA256 sha256; - sha256.buffer(in, (uint32_t)(size + sizeof(uint32_t)), out); - - delete[] in; - - // validate hash - bool validHash = false; - if (req->length - 8U == 32U) { - validHash = true; - for (uint8_t i = 0; i < 32U; i++) { - if (hash[i] != out[i]) { - validHash = false; - break; - } - } - } + std::string passwordForPeer = network->m_password; - // check if the peer is (not)whitelisted or blacklisted + // check if the peer is in the peer ACL list 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); + 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 { - LogWarning(LOG_NET, "PEER %u is not whitelisted", peerId); + 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; + } + } } - validAcl = false; } - if (validHash && validAcl) { - connection->connectionState(NET_STAT_WAITING_CONFIG); - network->writePeerACK(peerId); - LogInfoEx(LOG_NET, "PEER %u RPTK ACK, completed the login exchange", peerId); - } - 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); + 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)] = passwordForPeer.at(i); + + uint8_t out[32U]; + edac::SHA256 sha256; + sha256.buffer(in, (uint32_t)(size + sizeof(uint32_t)), out); + + delete[] in; + + // validate hash + bool validHash = false; + if (req->length - 8U == 32U) { + validHash = true; + for (uint8_t i = 0; i < 32U; i++) { + if (hash[i] != out[i]) { + validHash = false; + break; + } + } } + 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); + 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()) { 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: diff --git a/src/fne/network/RESTAPI.cpp b/src/fne/network/RESTAPI.cpp index ba27dfc8..0232da54 100644 --- a/src/fne/network/RESTAPI.cpp +++ b/src/fne/network/RESTAPI.cpp @@ -1215,10 +1215,15 @@ 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()) { - json::object peerObj = json::object(); - peerObj["peerId"].set(peerId); - peers.push_back(json::value(peerObj)); + 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(peerId); + + peers.push_back(json::value(peerObj)); + } } } @@ -1281,7 +1286,7 @@ void RESTAPI::restAPI_PutPeerDelete(const HTTPPayload& request, HTTPPayload& rep uint32_t peerId = req["peerId"].get(); - m_peerListLookup->removeEntry(peerId); + m_peerListLookup->eraseEntry(peerId); } /// @@ -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"; diff --git a/src/host/network/Network.cpp b/src/host/network/Network.cpp index 93e7c233..88f91e04 100644 --- a/src/host/network/Network.cpp +++ b/src/host/network/Network.cpp @@ -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: diff --git a/src/host/p25/packet/Voice.cpp b/src/host/p25/packet/Voice.cpp index 23988de7..adcaf030 100644 --- a/src/host/p25/packet/Voice.cpp +++ b/src/host/p25/packet/Voice.cpp @@ -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; } }