REST Additions and added NAK reasons (#56)

* Initial work for a peer whitelist/blacklist

* Remove forgotten debug log

* Remove extra line

* Use a dedicated file for white/blacklists

* Add support to REST for managing the peer white/blacklist

* Fix line spaces

* Move to one example file

* Add support for disconnecting a peer via the REST API; Add NAK reason for a peer ACL violation and for a peer reset; Add a REST endpoint for getting the current mode of peer ACL
3.6-maint
firealarmss 2 years ago committed by GitHub
parent a95f0b30b0
commit bd3e737adf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -155,6 +155,14 @@ void PeerListLookup::setEnabled(bool enabled)
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>

@ -72,6 +72,9 @@ namespace lookups
/// <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;

@ -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,

@ -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;
}
/// <summary>
/// Helper to reset a peer connection.
/// </summary>
/// <param name="peerId"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Helper to resolve the peer ID to its identity string.
/// </summary>
@ -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:

@ -259,6 +259,9 @@ namespace network
/// <summary>Closes connection to the network.</summary>
void close() override;
/// <summary></summary>
bool resetPeer(uint32_t peerId);
private:
friend class DiagNetwork;
friend class fne::TagDMRData;

@ -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);
}
/// <summary>
///
/// </summary>
/// <param name="request"></param>
/// <param name="reply"></param>
/// <param name="match"></param>
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<uint32_t>()) {
errorPayload(reply, "peerId was not a valid integer");
return;
}
uint32_t peerId = req["peerId"].get<uint32_t>();
m_network->resetPeer(peerId);
}
/// <summary>
///
/// </summary>
@ -1273,6 +1304,47 @@ void RESTAPI::restAPI_GetPeerCommit(const HTTPPayload& request, HTTPPayload& rep
reply.payload(response);
}
/// <summary>
///
/// </summary>
/// <param name="request"></param>
/// <param name="reply"></param>
/// <param name="match"></param>
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<std::string>(modeStr);
reply.payload(response);
}
/// <summary>
///
/// </summary>

@ -106,6 +106,8 @@ private:
void restAPI_GetPeerQuery(const HTTPPayload& request, HTTPPayload& reply, const network::rest::RequestMatch& match);
/// <summary></summary>
void restAPI_GetPeerCount(const HTTPPayload& request, HTTPPayload& reply, const network::rest::RequestMatch& match);
/// <summary></summary>
void restAPI_PutPeerReset(const HTTPPayload& request, HTTPPayload& reply, const network::rest::RequestMatch& match);
/// <summary></summary>
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);
/// <summary></summary>
void restAPI_GetPeerCommit(const HTTPPayload& request, HTTPPayload& reply, const network::rest::RequestMatch& match);
/// <summary></summary>
void restAPI_GetPeerMode(const HTTPPayload& request, HTTPPayload& reply, const network::rest::RequestMatch& match);
/// <summary></summary>
void restAPI_GetForceUpdate(const HTTPPayload& request, HTTPPayload& reply, const network::rest::RequestMatch& match);

@ -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"

@ -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:

Loading…
Cancel
Save

Powered by TurnKey Linux.