diff --git a/configs/fne-config.example.yml b/configs/fne-config.example.yml
index 2d2c9ad0..9549b4c5 100644
--- a/configs/fne-config.example.yml
+++ b/configs/fne-config.example.yml
@@ -71,8 +71,10 @@ master:
# Flag indicating whether or not a parrot TG call will generate a grant demand.
parrotGrantDemand: true
+ # Flag indicating whether or not a P25 ADJ_STS_BCAST will pass to any peers.
+ disallowAdjStsBcast: false
# Flag indicating whether or not a P25 ADJ_STS_BCAST will pass to connected external peers.
- disallowP25AdjStsBcast: true
+ disallowExtAdjStsBcast: true
#
# Talkgroup Rules Configuration
diff --git a/src/fne/network/FNENetwork.cpp b/src/fne/network/FNENetwork.cpp
index 73c597a3..f4a41c3f 100644
--- a/src/fne/network/FNENetwork.cpp
+++ b/src/fne/network/FNENetwork.cpp
@@ -87,7 +87,8 @@ FNENetwork::FNENetwork(HostFNE* host, const std::string& address, uint16_t port,
m_updateLookupTime(updateLookupTime * 60U),
m_softConnLimit(0U),
m_callInProgress(false),
- m_disallowP25AdjStsBcast(true),
+ m_disallowAdjStsBcast(false),
+ m_disallowExtAdjStsBcast(true),
m_reportPeerPing(reportPeerPing),
m_verbose(verbose)
{
@@ -118,16 +119,27 @@ FNENetwork::~FNENetwork()
///
void FNENetwork::setOptions(yaml::Node& conf, bool printOptions)
{
- m_disallowP25AdjStsBcast = conf["disallowP25AdjStsBcast"].as(true);
+ m_disallowAdjStsBcast = conf["disallowAdjStsBcast"].as(false);
+ m_disallowExtAdjStsBcast = conf["disallowExtAdjStsBcast"].as(true);
m_softConnLimit = conf["connectionLimit"].as(MAX_HARD_CONN_CAP);
if (m_softConnLimit > MAX_HARD_CONN_CAP) {
m_softConnLimit = MAX_HARD_CONN_CAP;
}
+ // always force disable ADJ_STS_BCAST to external peers if the all option
+ // is enabled
+ if (m_disallowAdjStsBcast) {
+ m_disallowExtAdjStsBcast = true;
+ }
+
if (printOptions) {
LogInfo(" Maximum Permitted Connections: %u", m_softConnLimit);
- LogInfo(" Disable P25 ADJ_STS_BCAST to external peers: %s", m_disallowP25AdjStsBcast ? "yes" : "no");
+ LogInfo(" Disable P25 ADJ_STS_BCAST to any peers: %s", m_disallowAdjStsBcast ? "yes" : "no");
+ if (m_disallowAdjStsBcast) {
+ LogWarning(LOG_NET, "NOTICE: All P25 ADJ_STS_BCAST messages will be blocked and dropped!");
+ }
+ LogInfo(" Disable P25 ADJ_STS_BCAST to external peers: %s", m_disallowExtAdjStsBcast ? "yes" : "no");
}
}
@@ -632,6 +644,11 @@ void* FNENetwork::threadedNetworkRx(void* arg)
LogInfoEx(LOG_NET, "PEER %u RPTC ACK, completed the configuration exchange", peerId);
json::object peerConfig = connection->config();
+ if (peerConfig["externalPeer"].is()) {
+ bool external = peerConfig["externalPeer"].get();
+ connection->isExternalPeer(external);
+ }
+
if (peerConfig["software"].is()) {
std::string software = peerConfig["software"].get();
LogInfoEx(LOG_NET, "PEER %u reports software %s", peerId, software.c_str());
diff --git a/src/fne/network/FNENetwork.h b/src/fne/network/FNENetwork.h
index 37a03a86..e652dee0 100644
--- a/src/fne/network/FNENetwork.h
+++ b/src/fne/network/FNENetwork.h
@@ -86,6 +86,7 @@ namespace network
m_pingsReceived(0U),
m_lastPing(0U),
m_lastACLUpdate(0U),
+ m_isExternalPeer(false),
m_config(),
m_pktLastSeq(0U),
m_pktNextSeq(1U)
@@ -109,6 +110,7 @@ namespace network
m_pingsReceived(0U),
m_lastPing(0U),
m_lastACLUpdate(0U),
+ m_isExternalPeer(false),
m_config(),
m_pktLastSeq(0U),
m_pktNextSeq(1U)
@@ -152,6 +154,9 @@ namespace network
/// Last ACL update sent.
__PROPERTY_PLAIN(uint64_t, lastACLUpdate);
+ /// Flag indicating this connection is from an external peer.
+ __PROPERTY_PLAIN(bool, isExternalPeer);
+
/// JSON objecting containing peer configuration information.
__PROPERTY_PLAIN(json::object, config);
@@ -278,7 +283,8 @@ namespace network
bool m_callInProgress;
- bool m_disallowP25AdjStsBcast;
+ bool m_disallowAdjStsBcast;
+ bool m_disallowExtAdjStsBcast;
bool m_reportPeerPing;
bool m_verbose;
diff --git a/src/fne/network/PeerNetwork.cpp b/src/fne/network/PeerNetwork.cpp
index 8555f0a6..02fb7306 100644
--- a/src/fne/network/PeerNetwork.cpp
+++ b/src/fne/network/PeerNetwork.cpp
@@ -117,7 +117,9 @@ bool PeerNetwork::writeConfig()
rcon["port"].set(m_restApiPort); // REST API Port
config["rcon"].set(rcon);
- config["software"].set(std::string(software)); // Software ID
+ bool external = true;
+ config["externalPeer"].set(external); // External Peer Marker
+ config["software"].set(std::string(software)); // Software ID
json::value v = json::value(config);
std::string json = v.serialize();
diff --git a/src/fne/network/fne/TagP25Data.cpp b/src/fne/network/fne/TagP25Data.cpp
index 7829a9d7..d399e9c9 100644
--- a/src/fne/network/fne/TagP25Data.cpp
+++ b/src/fne/network/fne/TagP25Data.cpp
@@ -244,6 +244,11 @@ bool TagP25Data::processFrame(const uint8_t* data, uint32_t len, uint32_t peerId
m_parrotFrames.push_back(std::make_tuple(copy, len, pktSeq, streamId, srcId, dstId));
}
+ // process TSDU from peer
+ if (!processTSDU(buffer, peerId, duid)) {
+ return false;
+ }
+
// repeat traffic to the connected peers
if (m_network->m_peers.size() > 0U) {
uint32_t i = 0U;
@@ -306,7 +311,7 @@ bool TagP25Data::processFrame(const uint8_t* data, uint32_t len, uint32_t peerId
routeRewrite(outboundPeerBuffer, dstPeerId, duid, dstId);
// process TSDUs going to external peers
- if (processTSDUExternal(outboundPeerBuffer, peerId, dstPeerId, duid)) {
+ if (processTSDUToExternal(outboundPeerBuffer, peerId, dstPeerId, duid)) {
peer.second->writeMaster({ NET_FUNC_PROTOCOL, NET_PROTOCOL_SUBFUNC_P25 }, outboundPeerBuffer, len, pktSeq, streamId);
if (m_network->m_debug) {
LogDebug(LOG_NET, "P25, srcPeer = %u, dstPeer = %u, duid = $%02X, lco = $%02X, MFId = $%02X, srcId = %u, dstId = %u, len = %u, pktSeq = %u, streamId = %u, external = %u",
@@ -424,12 +429,12 @@ void TagP25Data::routeRewrite(uint8_t* buffer, uint32_t peerId, uint8_t duid, ui
// rewrite destination TGID in the frame
__SET_UINT16(rewriteDstId, buffer, 8U);
- UInt8Array data = std::unique_ptr(new uint8_t[frameLength]);
- ::memset(data.get(), 0x00U, frameLength);
- ::memcpy(data.get(), buffer + 24U, frameLength);
-
// are we receiving a TSDU?
if (duid == P25_DUID_TSDU) {
+ UInt8Array data = std::unique_ptr(new uint8_t[frameLength]);
+ ::memset(data.get(), 0x00U, frameLength);
+ ::memcpy(data.get(), buffer + 24U, frameLength);
+
std::unique_ptr tsbk = lc::tsbk::TSBKFactory::createTSBK(data.get());
if (tsbk != nullptr) {
// handle standard P25 reference opcodes
@@ -503,6 +508,52 @@ bool TagP25Data::peerRewrite(uint32_t peerId, uint32_t& dstId, bool outbound)
return false;
}
+///
+/// Helper to process TSDUs being passed from a peer.
+///
+///
+/// Peer ID
+///
+bool TagP25Data::processTSDU(uint8_t* buffer, uint32_t peerId, uint8_t duid)
+{
+ // are we receiving a TSDU?
+ if (duid == P25_DUID_TSDU) {
+ uint32_t frameLength = buffer[23U];
+
+ UInt8Array data = std::unique_ptr(new uint8_t[frameLength]);
+ ::memset(data.get(), 0x00U, frameLength);
+ ::memcpy(data.get(), buffer + 24U, frameLength);
+
+ std::unique_ptr tsbk = lc::tsbk::TSBKFactory::createTSBK(data.get());
+ if (tsbk != nullptr) {
+ // handle standard P25 reference opcodes
+ switch (tsbk->getLCO()) {
+ case TSBK_OSP_ADJ_STS_BCAST:
+ {
+ if (m_network->m_disallowAdjStsBcast) {
+ // LogWarning(LOG_NET, "PEER %u, passing ADJ_STS_BCAST to internal peers is prohibited, dropping", peerId);
+ return false;
+ } else {
+ lc::tsbk::OSP_ADJ_STS_BCAST* osp = static_cast(tsbk.get());
+
+ if (m_network->m_verbose) {
+ LogMessage(LOG_NET, P25_TSDU_STR ", %s, sysId = $%03X, rfss = $%02X, site = $%02X, chId = %u, chNo = %u, svcClass = $%02X, peerId = %u", tsbk->toString().c_str(),
+ osp->getAdjSiteSysId(), osp->getAdjSiteRFSSId(), osp->getAdjSiteId(), osp->getAdjSiteChnId(), osp->getAdjSiteChnNo(), osp->getAdjSiteSvcClass(), peerId);
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ } else {
+ LogWarning(LOG_NET, "PEER %u, passing TSBK that failed to decode? tsbk == nullptr", peerId);
+ }
+ }
+
+ return true;
+}
+
///
/// Helper to process TSDUs being passed to an external peer.
///
@@ -510,7 +561,7 @@ bool TagP25Data::peerRewrite(uint32_t peerId, uint32_t& dstId, bool outbound)
/// Source Peer ID
/// Destination Peer ID
///
-bool TagP25Data::processTSDUExternal(uint8_t* buffer, uint32_t srcPeerId, uint32_t dstPeerId, uint8_t duid)
+bool TagP25Data::processTSDUToExternal(uint8_t* buffer, uint32_t srcPeerId, uint32_t dstPeerId, uint8_t duid)
{
// are we receiving a TSDU?
if (duid == P25_DUID_TSDU) {
@@ -526,15 +577,15 @@ bool TagP25Data::processTSDUExternal(uint8_t* buffer, uint32_t srcPeerId, uint32
switch (tsbk->getLCO()) {
case TSBK_OSP_ADJ_STS_BCAST:
{
- if (m_network->m_disallowP25AdjStsBcast) {
+ if (m_network->m_disallowExtAdjStsBcast) {
// LogWarning(LOG_NET, "PEER %u, passing ADJ_STS_BCAST to external peers is prohibited, dropping", dstPeerId);
return false;
} else {
lc::tsbk::OSP_ADJ_STS_BCAST* osp = static_cast(tsbk.get());
if (m_network->m_verbose) {
- LogMessage(LOG_NET, P25_TSDU_STR ", %s, sysId = $%03X, rfss = $%02X, site = $%02X, chId = %u, chNo = %u, svcClass = $%02X", tsbk->toString().c_str(),
- osp->getAdjSiteSysId(), osp->getAdjSiteRFSSId(), osp->getAdjSiteId(), osp->getAdjSiteChnId(), osp->getAdjSiteChnNo(), osp->getAdjSiteSvcClass());
+ LogMessage(LOG_NET, P25_TSDU_STR ", %s, sysId = $%03X, rfss = $%02X, site = $%02X, chId = %u, chNo = %u, svcClass = $%02X, peerId = %u", tsbk->toString().c_str(),
+ osp->getAdjSiteSysId(), osp->getAdjSiteRFSSId(), osp->getAdjSiteId(), osp->getAdjSiteChnId(), osp->getAdjSiteChnNo(), osp->getAdjSiteSvcClass(), srcPeerId);
}
}
}
diff --git a/src/fne/network/fne/TagP25Data.h b/src/fne/network/fne/TagP25Data.h
index e7d83928..819fc3f1 100644
--- a/src/fne/network/fne/TagP25Data.h
+++ b/src/fne/network/fne/TagP25Data.h
@@ -77,8 +77,10 @@ namespace network
/// Helper to route rewrite destination ID.
bool peerRewrite(uint32_t peerId, uint32_t& dstId, bool outbound = true);
+ /// Helper to process TSDUs being passed from a peer.
+ bool processTSDU(uint8_t* buffer, uint32_t peerId, uint8_t duid);
/// Helper to process TSDUs being passed to an external peer.
- bool processTSDUExternal(uint8_t* buffer, uint32_t srcPeerId, uint32_t dstPeerId, uint8_t duid);
+ bool processTSDUToExternal(uint8_t* buffer, uint32_t srcPeerId, uint32_t dstPeerId, uint8_t duid);
/// Helper to determine if the peer is permitted for traffic.
bool isPeerPermitted(uint32_t peerId, p25::lc::LC& control, uint8_t duid, uint32_t streamId);