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 file3.6-maint
parent
3335f7be39
commit
cba48ae54a
@ -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__
|
||||||
Loading…
Reference in new issue