diff --git a/src/common/lookups/PeerListLookup.cpp b/src/common/lookups/PeerListLookup.cpp index c26119f6..2222ee05 100644 --- a/src/common/lookups/PeerListLookup.cpp +++ b/src/common/lookups/PeerListLookup.cpp @@ -155,6 +155,14 @@ void PeerListLookup::setEnabled(bool enabled) m_enabled = enabled; } +/// +/// Gets whether the lookup is enabled. +/// +bool PeerListLookup::getEnabled() const +{ + return m_enabled; +} + /// /// Finds a table entry in this lookup table. /// diff --git a/src/common/lookups/PeerListLookup.h b/src/common/lookups/PeerListLookup.h index f13461cf..f324d2bf 100644 --- a/src/common/lookups/PeerListLookup.h +++ b/src/common/lookups/PeerListLookup.h @@ -72,6 +72,9 @@ namespace lookups /// 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; diff --git a/src/common/network/BaseNetwork.h b/src/common/network/BaseNetwork.h index dcb3e443..15bf1219 100644 --- a/src/common/network/BaseNetwork.h +++ b/src/common/network/BaseNetwork.h @@ -145,6 +145,8 @@ namespace network NET_CONN_NAK_FNE_UNAUTHORIZED, NET_CONN_NAK_BAD_CONN_STATE, NET_CONN_NAK_INVALID_CONFIG_DATA, + NET_CONN_NAK_PEER_RESET, + NET_CONN_NAK_PEER_ACL, NET_CONN_NAK_FNE_MAX_CONN, diff --git a/src/fne/network/FNENetwork.cpp b/src/fne/network/FNENetwork.cpp index 0fe19c45..b0b9dbd3 100644 --- a/src/fne/network/FNENetwork.cpp +++ b/src/fne/network/FNENetwork.cpp @@ -637,35 +637,42 @@ void* FNENetwork::threadedNetworkRx(void* arg) delete[] in; // validate hash - bool valid = false; + bool validHash = false; if (req->length - 8U == 32U) { - valid = true; + validHash = true; for (uint8_t i = 0; i < 32U; i++) { if (hash[i] != out[i]) { - valid = false; + validHash = false; break; } } } // 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); } - valid = false; + validAcl = false; } - if (valid) { + 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); - network->writePeerNAK(peerId, TAG_REPEATER_AUTH, NET_CONN_NAK_FNE_UNAUTHORIZED); + + 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->erasePeer(peerId); } @@ -1217,6 +1224,34 @@ bool FNENetwork::erasePeer(uint32_t peerId) return false; } +/// +/// Helper to reset a peer connection. +/// +/// +/// +bool FNENetwork::resetPeer(uint32_t peerId) +{ + if (peerId > 0 && (m_peers.find(peerId) != m_peers.end())) { + FNEPeerConnection* connection = m_peers[peerId]; + if (connection != nullptr) { + sockaddr_storage addr = connection->socketStorage(); + uint32_t addrLen = connection->sockStorageLen(); + + LogInfoEx(LOG_NET, "PEER %u (%s) resetting peer connection", peerId, connection->identity().c_str()); + + writePeerNAK(peerId, TAG_REPEATER_LOGIN, NET_CONN_NAK_PEER_RESET, addr, addrLen); + + delete connection; + erasePeer(peerId); + + return true; + } + } + + LogWarning(LOG_NET, "PEER %u reset failed; peer not found.", peerId); + return false; +} + /// /// Helper to resolve the peer ID to its identity string. /// @@ -1738,6 +1773,12 @@ void FNENetwork::logPeerNAKReason(uint32_t peerId, const char* tag, NET_CONN_NAK case NET_CONN_NAK_FNE_MAX_CONN: LogWarning(LOG_NET, "PEER %u NAK %s, reason = %u; FNE has reached maximum permitted connections", peerId, tag, (uint16_t)reason); break; + case NET_CONN_NAK_PEER_RESET: + LogWarning(LOG_NET, "PEER %u master NAK; FNE Called for a 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); + break; case NET_CONN_NAK_GENERAL_FAILURE: default: diff --git a/src/fne/network/FNENetwork.h b/src/fne/network/FNENetwork.h index 05ae37ca..35f58acf 100644 --- a/src/fne/network/FNENetwork.h +++ b/src/fne/network/FNENetwork.h @@ -259,6 +259,9 @@ namespace network /// Closes connection to the network. void close() override; + /// + bool resetPeer(uint32_t peerId); + private: friend class DiagNetwork; friend class fne::TagDMRData; diff --git a/src/fne/network/RESTAPI.cpp b/src/fne/network/RESTAPI.cpp index a046a1b6..ba27dfc8 100644 --- a/src/fne/network/RESTAPI.cpp +++ b/src/fne/network/RESTAPI.cpp @@ -571,6 +571,7 @@ void RESTAPI::initializeEndpoints() m_dispatcher.match(FNE_GET_PEER_QUERY).get(REST_API_BIND(RESTAPI::restAPI_GetPeerQuery, this)); m_dispatcher.match(FNE_GET_PEER_COUNT).get(REST_API_BIND(RESTAPI::restAPI_GetPeerCount, this)); + m_dispatcher.match(FNE_PUT_PEER_RESET).put(REST_API_BIND(RESTAPI::restAPI_PutPeerReset, this)); m_dispatcher.match(FNE_GET_RID_QUERY).get(REST_API_BIND(RESTAPI::restAPI_GetRIDQuery, this)); m_dispatcher.match(FNE_PUT_RID_ADD).put(REST_API_BIND(RESTAPI::restAPI_PutRIDAdd, this)); @@ -586,6 +587,7 @@ void RESTAPI::initializeEndpoints() m_dispatcher.match(FNE_PUT_PEER_ADD).put(REST_API_BIND(RESTAPI::restAPI_PutPeerAdd, this)); m_dispatcher.match(FNE_PUT_PEER_DELETE).put(REST_API_BIND(RESTAPI::restAPI_PutPeerDelete, this)); m_dispatcher.match(FNE_GET_PEER_COMMIT).get(REST_API_BIND(RESTAPI::restAPI_GetPeerCommit, this)); + m_dispatcher.match(FNE_GET_PEER_MODE).get(REST_API_BIND(RESTAPI::restAPI_GetPeerMode, this)); m_dispatcher.match(FNE_GET_FORCE_UPDATE).get(REST_API_BIND(RESTAPI::restAPI_GetForceUpdate, this)); @@ -873,6 +875,35 @@ void RESTAPI::restAPI_GetPeerCount(const HTTPPayload& request, HTTPPayload& repl reply.payload(response); } +/// +/// +/// +/// +/// +/// +void RESTAPI::restAPI_PutPeerReset(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match) +{ + if (!validateAuth(request, reply)) { + return; + } + + json::object req = json::object(); + if (!parseRequestBody(request, reply, req)) { + return; + } + + errorPayload(reply, "OK", HTTPPayload::OK); + + if (!req["peerId"].is()) { + errorPayload(reply, "peerId was not a valid integer"); + return; + } + + uint32_t peerId = req["peerId"].get(); + + m_network->resetPeer(peerId); +} + /// /// /// @@ -1273,6 +1304,47 @@ void RESTAPI::restAPI_GetPeerCommit(const HTTPPayload& request, HTTPPayload& rep reply.payload(response); } +/// +/// +/// +/// +/// +/// +void RESTAPI::restAPI_GetPeerMode(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match) +{ + if (!validateAuth(request, reply)) { + return; + } + + json::object response = json::object(); + setResponseDefaultStatus(response); + + lookups::PeerListLookup::Mode mode = m_peerListLookup->getMode(); + bool enabled = m_peerListLookup->getEnabled(); + + std::string modeStr; + + if (enabled) { + switch (mode) { + case lookups::PeerListLookup::WHITELIST: + modeStr = "WHITELIST"; + break; + case lookups::PeerListLookup::BLACKLIST: + modeStr = "BLACKLIST"; + break; + default: + modeStr = "UNKNOWN"; + break; + } + } + else { + modeStr = "DISABLED"; + } + + response["mode"].set(modeStr); + reply.payload(response); +} + /// /// /// diff --git a/src/fne/network/RESTAPI.h b/src/fne/network/RESTAPI.h index 4729edb1..516715f8 100644 --- a/src/fne/network/RESTAPI.h +++ b/src/fne/network/RESTAPI.h @@ -106,6 +106,8 @@ private: void restAPI_GetPeerQuery(const HTTPPayload& request, HTTPPayload& reply, const network::rest::RequestMatch& match); /// void restAPI_GetPeerCount(const HTTPPayload& request, HTTPPayload& reply, const network::rest::RequestMatch& match); + /// + void restAPI_PutPeerReset(const HTTPPayload& request, HTTPPayload& reply, const network::rest::RequestMatch& match); /// void restAPI_GetRIDQuery(const HTTPPayload& request, HTTPPayload& reply, const network::rest::RequestMatch& match); @@ -133,6 +135,8 @@ private: void restAPI_PutPeerDelete(const HTTPPayload& request, HTTPPayload& reply, const network::rest::RequestMatch& match); /// void restAPI_GetPeerCommit(const HTTPPayload& request, HTTPPayload& reply, const network::rest::RequestMatch& match); + /// + void restAPI_GetPeerMode(const HTTPPayload& request, HTTPPayload& reply, const network::rest::RequestMatch& match); /// void restAPI_GetForceUpdate(const HTTPPayload& request, HTTPPayload& reply, const network::rest::RequestMatch& match); diff --git a/src/fne/network/RESTDefines.h b/src/fne/network/RESTDefines.h index 51696957..061c6acf 100644 --- a/src/fne/network/RESTDefines.h +++ b/src/fne/network/RESTDefines.h @@ -22,6 +22,7 @@ #define FNE_GET_PEER_QUERY "/peer/query" #define FNE_GET_PEER_COUNT "/peer/count" +#define FNE_PUT_PEER_RESET "/peer/reset" #define FNE_GET_RID_QUERY "/rid/query" #define FNE_PUT_RID_ADD "/rid/add" @@ -37,6 +38,7 @@ #define FNE_PUT_PEER_ADD "/peer/add" #define FNE_PUT_PEER_DELETE "/peer/delete" #define FNE_GET_PEER_COMMIT "/peer/commit" +#define FNE_GET_PEER_MODE "/peer/mode" #define FNE_GET_FORCE_UPDATE "/force-update" diff --git a/src/host/network/Network.cpp b/src/host/network/Network.cpp index 9a1f7851..df810557 100644 --- a/src/host/network/Network.cpp +++ b/src/host/network/Network.cpp @@ -541,6 +541,12 @@ void Network::clock(uint32_t ms) case NET_CONN_NAK_FNE_MAX_CONN: LogWarning(LOG_NET, "PEER %u master NAK; FNE has reached maximum permitted connections, remotePeerId = %u", m_peerId, rtpHeader.getSSRC()); break; + case NET_CONN_NAK_PEER_RESET: + LogWarning(LOG_NET, "PEER %u master NAK; FNE Called for a 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()); + break; case NET_CONN_NAK_GENERAL_FAILURE: default: