Add support for peer blacklist and whitelist (#55)

* 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
3.6-maint
firealarmss 2 years ago committed by GitHub
parent 3335f7be39
commit cba48ae54a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -202,7 +202,17 @@ system:
# Radio ID ACL Configuration
#
radio_id:
# Full path to the identity table file.
# Full path to the Radio ID ACL file.
file: rid_acl.dat
# Amount of time between updates of identity table file. (minutes)
# Amount of time between updates of Radio ID ACL file. (minutes)
time: 2
# Peer whitelist and blacklist configuration
peer_acl:
enabled: true
# whitelist or blacklist
mode: whitelist
# Full path to the White/Blacklist file.
file: peer_whitelist.dat
# Amount of time between updates of White/Blacklist file. (minutes)
time: 1

@ -0,0 +1,3 @@
# Example blacklist or whitelist
1234
12345

@ -0,0 +1,245 @@
// SPDX-License-Identifier: GPL-2.0-only
/**
* Digital Voice Modem - Common Library
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / Common Library
* @derivedfrom MMDVMHost (https://github.com/g4klx/MMDVMHost)
* @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) 2024 Patrick McDonnell, W3AXL
* Copyright (c) 2024 Caleb, KO4UYJ
*
*/
#include "PeerListLookup.h"
#include "Log.h"
using namespace lookups;
#include <fstream>
#include <algorithm>
// ---------------------------------------------------------------------------
// Static Class Members
// ---------------------------------------------------------------------------
std::mutex PeerListLookup::m_mutex;
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the PeerListLookup class.
/// </summary>
/// <param name="listFile">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)
{
/* 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();
}
/// <summary>
/// Adds a new entry to the list.
/// </summary>
/// <param name="peerId">Unique peer ID to add.</param>
void PeerListLookup::addEntry(uint32_t peerId)
{
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);
}
}
/// <summary>
/// Removes an existing entry from the list.
/// </summary>
/// <param name="peerId">Unique peer ID to remove.</param>
void PeerListLookup::removeEntry(uint32_t peerId)
{
std::lock_guard<std::mutex> lock(m_mutex);
m_list.erase(std::remove(m_list.begin(), m_list.end(), peerId), m_list.end());
}
/// <summary>
/// Checks if a peer ID is in the list.
/// </summary>
/// <param name="peerId">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
{
std::lock_guard<std::mutex> lock(m_mutex);
bool found = std::find(m_list.begin(), m_list.end(), peerId) != m_list.end();
return found;
}
/// <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>
/// <returns>True if the peer ID is allowed, otherwise false.</returns>
bool PeerListLookup::isPeerAllowed(uint32_t peerId) const
{
if (!m_enabled) {
return true; // if not enabled, allow all peers
}
bool allowed = false;
if (m_mode == WHITELIST) {
allowed = isPeerInList(peerId);
} else if (m_mode == BLACKLIST) {
allowed = !isPeerInList(peerId);
}
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>
/// <param name="mode">The mode to set.</param>
void PeerListLookup::setMode(Mode mode)
{
std::lock_guard<std::mutex> lock(m_mutex);
m_mode = mode;
}
/// <summary>
/// Gets the current mode.
/// </summary>
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>
/// 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
// ---------------------------------------------------------------------------
/// <summary>
/// Loads the table from the passed lookup table file.
/// </summary>
/// <returns>True, if lookup table was loaded, otherwise false.</returns>
bool PeerListLookup::load()
{
if (m_filename.empty()) {
LogError(LOG_NET, "List file is empty");
return false;
}
std::ifstream file(m_filename, std::ifstream::in);
if (file.fail()) {
LogError("Cannot open the white/blacklist file: %s", m_filename.c_str());
return false;
}
m_list.clear();
std::lock_guard<std::mutex> lock(m_mutex);
std::string line;
while (std::getline(file, line)) {
if (line.length() > 0) {
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 list from file %s", peerId, m_filename.c_str());
}
}
}
file.close();
LogInfoEx(LOG_HOST, "Loaded %lu peers into list", m_list.size());
return !m_list.empty();
}
/// <summary>
/// Saves the table to the passed lookup table file.
/// </summary>
/// <returns>True, if lookup table was saved, otherwise false.</returns>
bool PeerListLookup::save()
{
if (m_filename.empty()) {
LogError(LOG_NET, "List file is empty");
return false;
}
std::ofstream file(m_filename, std::ofstream::out);
if (file.fail()) {
LogError("Cannot open the file: %s", m_filename.c_str());
return false;
}
std::lock_guard<std::mutex> lock(m_mutex);
for (auto& peerId : m_list) {
file << peerId << "\n";
}
file.close();
LogInfoEx(LOG_HOST, "Saved %lu peers to list", m_list.size());
return true;
}

@ -0,0 +1,94 @@
// SPDX-License-Identifier: GPL-2.0-only
/**
* Digital Voice Modem - Common Library
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / Common Library
* @derivedfrom MMDVMHost (https://github.com/g4klx/MMDVMHost)
* @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) 2024 Patrick McDonnell, W3AXL
* Copyright (c) 2024 Caleb, KO4UYJ
*
*/
#if !defined(__PEER_LIST_LOOKUP_H__)
#define __PEER_LIST_LOOKUP_H__
#include "common/Defines.h"
#include "common/lookups/LookupTable.h"
#include <string>
#include <vector>
#include <mutex>
namespace lookups
{
// ---------------------------------------------------------------------------
// Class Declaration
// Implements a threading lookup table class that contains peer whitelist
// and blacklist.
// ---------------------------------------------------------------------------
class HOST_SW_API PeerListLookup : public LookupTable<uint32_t> {
public:
enum Mode {
WHITELIST,
BLACKLIST
};
/// <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;
/// <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);
/// <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;
/// <summary>Commit the table.</summary>
void commit();
/// <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>Finds a table entry in this lookup table.</summary>
uint32_t find(uint32_t id) override;
protected:
bool load() override;
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;
};
} // namespace lookups
#endif // __PEER_LIST_LOOKUP_H__

@ -57,6 +57,7 @@ HostFNE::HostFNE(const std::string& confFile) :
m_nxdnEnabled(false),
m_ridLookup(nullptr),
m_tidLookup(nullptr),
m_peerListLookup(nullptr),
m_peerNetworks(),
m_pingTime(5U),
m_maxMissedPings(5U),
@ -283,11 +284,17 @@ int HostFNE::run()
m_tidLookup->stop();
delete m_tidLookup;
}
if (m_ridLookup != nullptr) {
m_ridLookup->stop();
delete m_ridLookup;
}
if (m_peerListLookup != nullptr) {
m_peerListLookup->stop();
delete m_peerListLookup;
}
return EXIT_SUCCESS;
}
@ -340,6 +347,18 @@ bool HostFNE::readParams()
std::string talkgroupConfig = talkgroupRules["file"].as<std::string>();
uint32_t talkgroupConfigReload = talkgroupRules["time"].as<uint32_t>(30U);
std::string peerListLookupFile = systemConf["peer_acl"]["file"].as<std::string>();
bool peerListLookupEnable = systemConf["peer_acl"]["enabled"].as<bool>();
std::string peerListModeStr = systemConf["peer_acl"]["mode"].as<std::string>("whitelist");
uint32_t peerListConfigReload = systemConf["peer_acl"]["time"].as<uint32_t>(30U);
lookups::PeerListLookup::Mode peerListMode;
if (peerListModeStr == "blacklist") {
peerListMode = lookups::PeerListLookup::BLACKLIST;
} else {
peerListMode = lookups::PeerListLookup::WHITELIST;
}
LogInfo("Talkgroup Rule Lookups");
LogInfo(" File: %s", talkgroupConfig.length() > 0U ? talkgroupConfig.c_str() : "None");
if (talkgroupConfigReload > 0U)
@ -349,6 +368,17 @@ bool HostFNE::readParams()
m_tidLookup->sendTalkgroups(sendTalkgroups);
m_tidLookup->read();
// try to load peer whitelist/blacklist
LogInfo("Peer List Lookups");
LogInfo(" Enabled: %s", peerListLookupEnable ? "Yes" : "No");
LogInfo(" Mode: %s", peerListMode == lookups::PeerListLookup::BLACKLIST ? "Blacklist" : "Whitelist");
LogInfo(" File: %s", peerListLookupFile.length() > 0U ? peerListLookupFile.c_str() : "None");
if (peerListConfigReload > 0U)
LogInfo(" Reload: %u mins", peerListConfigReload);
m_peerListLookup = new PeerListLookup(peerListLookupFile, peerListMode, peerListConfigReload, peerListLookupEnable);
m_peerListLookup->read();
return true;
}
@ -414,7 +444,7 @@ bool HostFNE::initializeRESTAPI()
// initialize network remote command
if (restApiEnable) {
m_RESTAPI = new RESTAPI(restApiAddress, restApiPort, restApiPassword, restApiSSLKey, restApiSSLCert, restApiEnableSSL, this, restApiDebug);
m_RESTAPI->setLookups(m_ridLookup, m_tidLookup);
m_RESTAPI->setLookups(m_ridLookup, m_tidLookup, m_peerListLookup);
bool ret = m_RESTAPI->open();
if (!ret) {
delete m_RESTAPI;
@ -521,7 +551,7 @@ bool HostFNE::createMasterNetwork()
parrotDelay, parrotGrantDemand, m_allowActivityTransfer, m_allowDiagnosticTransfer, m_pingTime, m_updateLookupTime);
m_network->setOptions(masterConf, true);
m_network->setLookups(m_ridLookup, m_tidLookup);
m_network->setLookups(m_ridLookup, m_tidLookup, m_peerListLookup);
if (m_RESTAPI != nullptr) {
m_RESTAPI->setNetwork(m_network);

@ -16,6 +16,7 @@
#include "Defines.h"
#include "common/lookups/RadioIdLookup.h"
#include "common/lookups/TalkgroupRulesLookup.h"
#include "common/lookups/PeerListLookup.h"
#include "common/yaml/Yaml.h"
#include "common/Timer.h"
#include "network/FNENetwork.h"
@ -67,6 +68,7 @@ private:
lookups::RadioIdLookup* m_ridLookup;
lookups::TalkgroupRulesLookup* m_tidLookup;
lookups::PeerListLookup* m_peerListLookup;
std::unordered_map<std::string, network::PeerNetwork*> m_peerNetworks;

@ -87,6 +87,7 @@ FNENetwork::FNENetwork(HostFNE* host, const std::string& address, uint16_t port,
m_parrotOnlyOriginating(false),
m_ridLookup(nullptr),
m_tidLookup(nullptr),
m_peerListLookup(nullptr),
m_status(NET_STAT_INVALID),
m_peers(),
m_peerAffiliations(),
@ -207,14 +208,15 @@ void FNENetwork::setOptions(yaml::Node& conf, bool printOptions)
}
/// <summary>
/// Sets the instances of the Radio ID and Talkgroup Rules lookup tables.
/// Sets the instances of the Radio ID, Talkgroup Rules, and Peer List lookup tables.
/// </summary>
/// <param name="ridLookup">Radio ID Lookup Table Instance</param>
/// <param name="tidLookup">Talkgroup Rules Lookup Table Instance</param>
void FNENetwork::setLookups(lookups::RadioIdLookup* ridLookup, lookups::TalkgroupRulesLookup* tidLookup)
void FNENetwork::setLookups(lookups::RadioIdLookup* ridLookup, lookups::TalkgroupRulesLookup* tidLookup, lookups::PeerListLookup* peerListLookup)
{
m_ridLookup = ridLookup;
m_tidLookup = tidLookup;
m_peerListLookup = peerListLookup;
}
/// <summary>
@ -646,6 +648,16 @@ void* FNENetwork::threadedNetworkRx(void* arg)
}
}
// check if the peer is (not)whitelisted or blacklisted
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;
}
if (valid) {
connection->connectionState(NET_STAT_WAITING_CONFIG);
network->writePeerACK(peerId);

@ -19,6 +19,7 @@
#include "common/lookups/AffiliationLookup.h"
#include "common/lookups/RadioIdLookup.h"
#include "common/lookups/TalkgroupRulesLookup.h"
#include "common/lookups/PeerListLookup.h"
#include "fne/network/influxdb/InfluxDB.h"
#include "host/network/Network.h"
@ -242,7 +243,7 @@ namespace network
fne::TagNXDNData* nxdnTrafficHandler() const { return m_tagNXDN; }
/// <summary>Sets the instances of the Radio ID and Talkgroup Rules lookup tables.</summary>
void setLookups(lookups::RadioIdLookup* ridLookup, lookups::TalkgroupRulesLookup* tidLookup);
void setLookups(lookups::RadioIdLookup* ridLookup, lookups::TalkgroupRulesLookup* tidLookup, lookups::PeerListLookup* peerListLookup);
/// <summary>Sets endpoint preshared encryption key.</summary>
void setPresharedKey(const uint8_t* presharedKey);
@ -286,6 +287,7 @@ namespace network
lookups::RadioIdLookup* m_ridLookup;
lookups::TalkgroupRulesLookup* m_tidLookup;
lookups::PeerListLookup* m_peerListLookup;
NET_CONN_STATUS m_status;

@ -435,6 +435,7 @@ RESTAPI::RESTAPI(const std::string& address, uint16_t port, const std::string& p
m_network(nullptr),
m_ridLookup(nullptr),
m_tidLookup(nullptr),
m_peerListLookup(nullptr),
m_authTokens()
{
assert(!address.empty());
@ -483,10 +484,11 @@ RESTAPI::~RESTAPI() = default;
/// </summary>
/// <param name="ridLookup">Radio ID Lookup Table Instance</param>
/// <param name="tidLookup">Talkgroup Rules Lookup Table Instance</param>
void RESTAPI::setLookups(lookups::RadioIdLookup* ridLookup, lookups::TalkgroupRulesLookup* tidLookup)
void RESTAPI::setLookups(lookups::RadioIdLookup* ridLookup, lookups::TalkgroupRulesLookup* tidLookup, ::lookups::PeerListLookup* peerListLookup)
{
m_ridLookup = ridLookup;
m_tidLookup = tidLookup;
m_peerListLookup = peerListLookup;
}
/// <summary>
@ -580,6 +582,11 @@ void RESTAPI::initializeEndpoints()
m_dispatcher.match(FNE_PUT_TGID_DELETE).put(REST_API_BIND(RESTAPI::restAPI_PutTGDelete, this));
m_dispatcher.match(FNE_GET_TGID_COMMIT).get(REST_API_BIND(RESTAPI::restAPI_GetTGCommit, this));
m_dispatcher.match(FNE_GET_PEER_LIST).get(REST_API_BIND(RESTAPI::restAPI_GetPeerList, this));
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_FORCE_UPDATE).get(REST_API_BIND(RESTAPI::restAPI_GetForceUpdate, this));
m_dispatcher.match(FNE_GET_RELOAD_TGS).get(REST_API_BIND(RESTAPI::restAPI_GetReloadTGs, this));
@ -1160,6 +1167,112 @@ void RESTAPI::restAPI_GetTGCommit(const HTTPPayload& request, HTTPPayload& reply
reply.payload(response);
}
/// <summary>
///
/// </summary>
/// <param name="request"></param>
/// <param name="reply"></param>
/// <param name="match"></param>
void RESTAPI::restAPI_GetPeerList(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match)
{
if (!validateAuth(request, reply)) {
return;
}
json::object response = json::object();
setResponseDefaultStatus(response);
json::array peers = json::array();
if (m_peerListLookup != nullptr) {
for (const auto& peerId : m_peerListLookup->getPeerList()) {
json::object peerObj = json::object();
peerObj["peerId"].set<uint32_t>(peerId);
peers.push_back(json::value(peerObj));
}
}
response["peers"].set<json::array>(peers);
reply.payload(response);
}
/// <summary>
///
/// </summary>
/// <param name="request"></param>
/// <param name="reply"></param>
/// <param name="match"></param>
void RESTAPI::restAPI_PutPeerAdd(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_peerListLookup->addEntry(peerId);
}
/// <summary>
///
/// </summary>
/// <param name="request"></param>
/// <param name="reply"></param>
/// <param name="match"></param>
void RESTAPI::restAPI_PutPeerDelete(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_peerListLookup->removeEntry(peerId);
}
/// <summary>
///
/// </summary>
/// <param name="request"></param>
/// <param name="reply"></param>
/// <param name="match"></param>
void RESTAPI::restAPI_GetPeerCommit(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match)
{
if (!validateAuth(request, reply)) {
return;
}
json::object response = json::object();
setResponseDefaultStatus(response);
m_peerListLookup->commit();
reply.payload(response);
}
/// <summary>
///
/// </summary>

@ -47,7 +47,7 @@ public:
~RESTAPI() override;
/// <summary>Sets the instances of the Radio ID and Talkgroup ID lookup tables.</summary>
void setLookups(::lookups::RadioIdLookup* ridLookup, ::lookups::TalkgroupRulesLookup* tidLookup);
void setLookups(::lookups::RadioIdLookup* ridLookup, ::lookups::TalkgroupRulesLookup* tidLookup, ::lookups::PeerListLookup* peerListLookup);
/// <summary>Sets the instance of the FNE network.</summary>
void setNetwork(::network::FNENetwork* network);
@ -78,6 +78,7 @@ private:
::lookups::RadioIdLookup* m_ridLookup;
::lookups::TalkgroupRulesLookup* m_tidLookup;
::lookups::PeerListLookup* m_peerListLookup;
typedef std::unordered_map<std::string, uint64_t>::value_type AuthTokenValueType;
std::unordered_map<std::string, uint64_t> m_authTokens;
@ -124,6 +125,15 @@ private:
/// <summary></summary>
void restAPI_GetTGCommit(const HTTPPayload& request, HTTPPayload& reply, const network::rest::RequestMatch& match);
/// <summary></summary>
void restAPI_GetPeerList(const HTTPPayload& request, HTTPPayload& reply, const network::rest::RequestMatch& match);
/// <summary></summary>
void restAPI_PutPeerAdd(const HTTPPayload& request, HTTPPayload& reply, const network::rest::RequestMatch& match);
/// <summary></summary>
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_GetForceUpdate(const HTTPPayload& request, HTTPPayload& reply, const network::rest::RequestMatch& match);

@ -33,6 +33,11 @@
#define FNE_PUT_TGID_DELETE "/tg/delete"
#define FNE_GET_TGID_COMMIT "/tg/commit"
#define FNE_GET_PEER_LIST "/peer/list"
#define FNE_PUT_PEER_ADD "/peer/add"
#define FNE_PUT_PEER_DELETE "/peer/delete"
#define FNE_GET_PEER_COMMIT "/peer/commit"
#define FNE_GET_FORCE_UPDATE "/force-update"
#define FNE_GET_RELOAD_TGS "/reload-tgs"

Loading…
Cancel
Save

Powered by TurnKey Linux.