diff --git a/configs/fne-config.example.yml b/configs/fne-config.example.yml index 3e597566..22b49265 100644 --- a/configs/fne-config.example.yml +++ b/configs/fne-config.example.yml @@ -73,6 +73,9 @@ master: # Flag indicating whether or not a parrot TG call will only be sent to the originating peer. parrotOnlyToOrginiatingPeer: false + # Flag indicating whether or not a grant responses will only be sent to TGs with affiliations, if the TG is configured for affiliation gating. + restrictGrantToAffiliatedOnly: false + # Flag indicating whether or not a adjacent site broadcasts will pass to any peers. disallowAdjStsBcast: false # Flag indicating whether or not a P25 ADJ_STS_BCAST will pass to connected external peers. diff --git a/src/fne/network/FNENetwork.cpp b/src/fne/network/FNENetwork.cpp index 1f0831c7..c8210be0 100644 --- a/src/fne/network/FNENetwork.cpp +++ b/src/fne/network/FNENetwork.cpp @@ -97,6 +97,7 @@ FNENetwork::FNENetwork(HostFNE* host, const std::string& address, uint16_t port, m_disallowAdjStsBcast(false), m_disallowExtAdjStsBcast(true), m_allowConvSiteAffOverride(false), + m_restrictGrantToAffOnly(false), m_enableInfluxDB(false), m_influxServerAddress("127.0.0.1"), m_influxServerPort(8086U), @@ -161,6 +162,7 @@ void FNENetwork::setOptions(yaml::Node& conf, bool printOptions) } m_parrotOnlyOriginating = conf["parrotOnlyToOrginiatingPeer"].as(false); + m_restrictGrantToAffOnly = conf["restrictGrantToAffiliatedOnly"].as(false); if (printOptions) { LogInfo(" Maximum Permitted Connections: %u", m_softConnLimit); @@ -170,6 +172,7 @@ void FNENetwork::setOptions(yaml::Node& conf, bool printOptions) } LogInfo(" Disable P25 ADJ_STS_BCAST to external peers: %s", m_disallowExtAdjStsBcast ? "yes" : "no"); LogInfo(" Allow conventional sites to override affiliation and receive all traffic: %s", m_allowConvSiteAffOverride ? "yes" : "no"); + LogInfo(" Restrict grant response by affiliation: %s", m_restrictGrantToAffOnly ? "yes" : "no"); LogInfo(" InfluxDB Reporting Enabled: %s", m_enableInfluxDB ? "yes" : "no"); if (m_enableInfluxDB) { LogInfo(" InfluxDB Address: %s", m_influxServerAddress.c_str()); diff --git a/src/fne/network/FNENetwork.h b/src/fne/network/FNENetwork.h index 78610c14..29aa2d6a 100644 --- a/src/fne/network/FNENetwork.h +++ b/src/fne/network/FNENetwork.h @@ -305,6 +305,7 @@ namespace network bool m_disallowAdjStsBcast; bool m_disallowExtAdjStsBcast; bool m_allowConvSiteAffOverride; + bool m_restrictGrantToAffOnly; bool m_enableInfluxDB; std::string m_influxServerAddress; diff --git a/src/fne/network/fne/TagP25Data.cpp b/src/fne/network/fne/TagP25Data.cpp index bbff6ace..e1566c5a 100644 --- a/src/fne/network/fne/TagP25Data.cpp +++ b/src/fne/network/fne/TagP25Data.cpp @@ -274,7 +274,7 @@ bool TagP25Data::processFrame(const uint8_t* data, uint32_t len, uint32_t peerId } // process TSDU from peer - if (!processTSDU(buffer, peerId, duid)) { + if (!processTSDUFrom(buffer, peerId, duid)) { return false; } @@ -288,6 +288,11 @@ bool TagP25Data::processFrame(const uint8_t* data, uint32_t len, uint32_t peerId continue; } + // process TSDU to peer + if (!processTSDUTo(buffer, peer.first, duid)) { + continue; + } + // every 5 peers flush the queue if (i % 5U == 0U) { m_network->m_frameQueue->flushQueue(); @@ -639,7 +644,7 @@ bool TagP25Data::peerRewrite(uint32_t peerId, uint32_t& dstId, bool outbound) /// /// Peer ID /// -bool TagP25Data::processTSDU(uint8_t* buffer, uint32_t peerId, uint8_t duid) +bool TagP25Data::processTSDUFrom(uint8_t* buffer, uint32_t peerId, uint8_t duid) { // are we receiving a TSDU? if (duid == P25_DUID_TSDU) { @@ -701,6 +706,77 @@ bool TagP25Data::processTSDU(uint8_t* buffer, uint32_t peerId, uint8_t duid) return true; } +/// +/// Helper to process TSDUs being passed to a peer. +/// +/// +/// Peer ID +/// +bool TagP25Data::processTSDUTo(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) { + uint32_t srcId = tsbk->getSrcId(); + uint32_t dstId = tsbk->getDstId(); + + FNEPeerConnection* connection = nullptr; + if (peerId > 0 && (m_network->m_peers.find(peerId) != m_network->m_peers.end())) { + connection = m_network->m_peers[peerId]; + } + + // handle standard P25 reference opcodes + switch (tsbk->getLCO()) { + case TSBK_IOSP_GRP_VCH: + { + if (m_network->m_restrictGrantToAffOnly) { + lookups::TalkgroupRuleGroupVoice tg = m_network->m_tidLookup->find(dstId); + if (tg.config().affiliated()) { + uint32_t lookupPeerId = peerId; + if (connection != nullptr) { + if (connection->ccPeerId() > 0U) + lookupPeerId = connection->ccPeerId(); + } + + // check the affiliations for this peer to see if we can repeat the TSDU + lookups::AffiliationLookup* aff = m_network->m_peerAffiliations[lookupPeerId]; + if (aff == nullptr) { + std::string peerIdentity = m_network->resolvePeerIdentity(lookupPeerId); + LogError(LOG_NET, "PEER %u (%s) has an invalid affiliations lookup? This shouldn't happen BUGBUG.", lookupPeerId, peerIdentity.c_str()); + return false; // this will cause no TSDU to pass for this peer now...I'm not sure this is good behavior + } + else { + if (m_debug) { + std::string peerIdentity = m_network->resolvePeerIdentity(lookupPeerId); + LogDebug(LOG_NET, "PEER %u (%s) can fuck off there's no affiliations.", lookupPeerId, peerIdentity.c_str()); // just so Faulty can see more "salty" log messages + } + if (!aff->hasGroupAff(dstId)) { + return false; + } + } + } + } + } + break; + default: + break; + } + } else { + std::string peerIdentity = m_network->resolvePeerIdentity(peerId); + LogWarning(LOG_NET, "PEER %u (%s), passing TSBK that failed to decode? tsbk == nullptr", peerId, peerIdentity.c_str()); + } + } + + return true; +} + /// /// Helper to process TSDUs being passed to an external peer. /// diff --git a/src/fne/network/fne/TagP25Data.h b/src/fne/network/fne/TagP25Data.h index d265fd2d..64800c16 100644 --- a/src/fne/network/fne/TagP25Data.h +++ b/src/fne/network/fne/TagP25Data.h @@ -101,7 +101,9 @@ namespace network 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); + bool processTSDUFrom(uint8_t* buffer, uint32_t peerId, uint8_t duid); + /// Helper to process TSDUs being passed to a peer. + bool processTSDUTo(uint8_t* buffer, uint32_t peerId, uint8_t duid); /// Helper to process TSDUs being passed to an external peer. bool processTSDUToExternal(uint8_t* buffer, uint32_t srcPeerId, uint32_t dstPeerId, uint8_t duid);