From 62e79752e280e42ef1adaa6eb7265c1fd4e44668 Mon Sep 17 00:00:00 2001 From: Bryan Biedenkapp Date: Sun, 8 Nov 2026 21:34:55 -0500 Subject: [PATCH] when disallowUnitToUnit is enabled both inbound and outbound U2U is blocked; --- configs/config.example.yml | 2 +- src/common/network/Network.cpp | 11 +++++++++++ src/common/network/Network.h | 16 ++++++++++++++-- src/host/Host.Config.cpp | 2 +- src/host/dmr/Slot.cpp | 3 +++ src/host/nxdn/packet/ControlSignaling.cpp | 3 +++ src/host/nxdn/packet/Data.cpp | 3 +++ src/host/nxdn/packet/Voice.cpp | 3 +++ src/host/p25/packet/ControlSignaling.cpp | 14 ++++++++++++++ src/host/p25/packet/Voice.cpp | 3 +++ src/host/p25/phase2/Control.cpp | 4 ++++ 11 files changed, 60 insertions(+), 4 deletions(-) diff --git a/configs/config.example.yml b/configs/config.example.yml index 7412817b..2053ed30 100644 --- a/configs/config.example.yml +++ b/configs/config.example.yml @@ -106,7 +106,7 @@ network: # Maximum allowable DMR network jitter. jitter: 360 - # Flag indicating whether inbound unit-to-unit calls from the network will be discarded. + # Flag indicating whether unit-to-unit calls will be discarded in both network directions. disallowUnitToUnit: false # Flag indicating whether DMR slot 1 traffic will be passed. diff --git a/src/common/network/Network.cpp b/src/common/network/Network.cpp index ad5b15ed..cc73972a 100644 --- a/src/common/network/Network.cpp +++ b/src/common/network/Network.cpp @@ -115,6 +115,17 @@ Network::~Network() delete m_mux; } +/* Writes a grant request unless unit-to-unit network traffic is disabled. */ + +bool Network::writeGrantReq(const uint8_t mode, const uint32_t srcId, const uint32_t dstId, + const uint8_t slot, const bool unitToUnit) +{ + if (m_disallowUnitToUnit && unitToUnit) + return false; + + return BaseNetwork::writeGrantReq(mode, srcId, dstId, slot, unitToUnit); +} + /* Resets the DMR ring buffer for the given slot. */ void Network::resetDMR(uint32_t slotNo) diff --git a/src/common/network/Network.h b/src/common/network/Network.h index e804d7e1..2014a01d 100644 --- a/src/common/network/Network.h +++ b/src/common/network/Network.h @@ -163,7 +163,7 @@ namespace network * @param allowActivityTransfer Flag indicating that the system activity logs will be sent to the network. * @param allowDiagnosticTransfer Flag indicating that the system diagnostic logs will be sent to the network. * @param updateLookup Flag indicating that the system will accept radio ID and talkgroup ID lookups from the network. - * @param disallowUnitToUnit Flag indicating that inbound unit-to-unit traffic will be discarded. + * @param disallowUnitToUnit Flag indicating that network unit-to-unit traffic will be discarded. */ Network(const std::string& address, uint16_t port, uint16_t localPort, uint32_t peerId, const std::string& password, bool duplex, bool debug, bool dmr, bool p25, bool nxdn, bool analog, bool slot1, bool slot2, @@ -173,6 +173,18 @@ namespace network */ ~Network() override; + /** + * @brief Writes a grant request unless unit-to-unit network traffic is disabled. + * @param mode DVM protocol mode requesting the grant. + * @param srcId Source subscriber ID. + * @param dstId Destination subscriber or talkgroup ID. + * @param slot DMR slot number, or zero for protocols without slots. + * @param unitToUnit Flag indicating an individual-call grant request. + * @return True if the request was written; otherwise false. + */ + bool writeGrantReq(const uint8_t mode, const uint32_t srcId, const uint32_t dstId, + const uint8_t slot, const bool unitToUnit); + /** * @brief Resets the DMR ring buffer for the given slot. * @param slotNo DMR slot ring buffer to reset. @@ -334,7 +346,7 @@ namespace network DECLARE_RO_PROPERTY_PLAIN(uint16_t, pktLastSeq); /** - * @brief Flag indicating that inbound unit-to-unit traffic is discarded. + * @brief Flag indicating that network unit-to-unit traffic is discarded. */ DECLARE_RO_PROPERTY_PLAIN(bool, disallowUnitToUnit); diff --git a/src/host/Host.Config.cpp b/src/host/Host.Config.cpp index c63014b3..3b6e1ede 100644 --- a/src/host/Host.Config.cpp +++ b/src/host/Host.Config.cpp @@ -996,7 +996,7 @@ bool Host::createNetwork() LogInfo(" Allow Status Transfer: %s", m_allowStatusTransfer ? "yes" : "no"); LogInfo(" Update Lookups: %s", updateLookup ? "yes" : "no"); LogInfo(" Save Network Lookups: %s", saveLookup ? "yes" : "no"); - LogInfo(" Disallow Network Unit-to-Unit: %s", disallowUnitToUnit ? "yes" : "no"); + LogInfo(" Disallow Network Unit-to-Unit Calls: %s", disallowUnitToUnit ? "yes" : "no"); LogInfo(" Encrypted: %s", encrypted ? "yes" : "no"); LogInfo(" KMF Encrypted: %s", kmfEncrypted ? "yes" : "no"); diff --git a/src/host/dmr/Slot.cpp b/src/host/dmr/Slot.cpp index 5a680401..0b7662b5 100644 --- a/src/host/dmr/Slot.cpp +++ b/src/host/dmr/Slot.cpp @@ -1529,6 +1529,9 @@ void Slot::writeNetwork(const uint8_t* data, DataType::E dataType, FLCO::E flco, if (s_network == nullptr) return; + if (s_network->disallowUnitToUnit() && flco == FLCO::PRIVATE) + return; + data::NetData dmrData; dmrData.setSlotNo(m_slotNo); dmrData.setDataType(dataType); diff --git a/src/host/nxdn/packet/ControlSignaling.cpp b/src/host/nxdn/packet/ControlSignaling.cpp index abb961d6..60e799a3 100644 --- a/src/host/nxdn/packet/ControlSignaling.cpp +++ b/src/host/nxdn/packet/ControlSignaling.cpp @@ -430,6 +430,9 @@ void ControlSignaling::writeNetwork(const uint8_t *data, uint32_t len) if (m_nxdn->m_network == nullptr) return; + if (m_nxdn->m_network->disallowUnitToUnit() && !m_nxdn->m_rfLC.getGroup()) + return; + if (m_nxdn->m_rfTimeoutTimer.isRunning() && m_nxdn->m_rfTimeoutTimer.hasExpired()) return; diff --git a/src/host/nxdn/packet/Data.cpp b/src/host/nxdn/packet/Data.cpp index dfb2e50e..0863d8b7 100644 --- a/src/host/nxdn/packet/Data.cpp +++ b/src/host/nxdn/packet/Data.cpp @@ -411,6 +411,9 @@ void Data::writeNetwork(const uint8_t *data, uint32_t len) if (m_nxdn->m_network == nullptr) return; + if (m_nxdn->m_network->disallowUnitToUnit() && !m_nxdn->m_rfLC.getGroup()) + return; + if (m_nxdn->m_rfTimeoutTimer.isRunning() && m_nxdn->m_rfTimeoutTimer.hasExpired()) return; diff --git a/src/host/nxdn/packet/Voice.cpp b/src/host/nxdn/packet/Voice.cpp index c3a39397..0c9be650 100644 --- a/src/host/nxdn/packet/Voice.cpp +++ b/src/host/nxdn/packet/Voice.cpp @@ -1190,6 +1190,9 @@ void Voice::writeNetwork(const uint8_t *data, uint32_t len) if (m_nxdn->m_network == nullptr) return; + if (m_nxdn->m_network->disallowUnitToUnit() && !m_nxdn->m_rfLC.getGroup()) + return; + if (m_nxdn->m_rfTimeoutTimer.isRunning() && m_nxdn->m_rfTimeoutTimer.hasExpired()) return; diff --git a/src/host/p25/packet/ControlSignaling.cpp b/src/host/p25/packet/ControlSignaling.cpp index 1527b868..9c45d1a8 100644 --- a/src/host/p25/packet/ControlSignaling.cpp +++ b/src/host/p25/packet/ControlSignaling.cpp @@ -1603,6 +1603,17 @@ void ControlSignaling::writeNetworkRF(lc::TSBK* tsbk, const uint8_t* data, bool if (m_p25->m_network == nullptr) return; + if (m_p25->m_network->disallowUnitToUnit()) { + switch (tsbk->getLCO()) { + case TSBKO::IOSP_UU_VCH: + case TSBKO::IOSP_UU_ANS: + case TSBKO::OSP_UU_VCH_GRANT_UPD: + return; + default: + break; + } + } + if (m_p25->m_rfTimeoutTimer.isRunning() && m_p25->m_rfTimeoutTimer.hasExpired()) return; @@ -1626,6 +1637,9 @@ void ControlSignaling::writeNetworkRF(lc::TDULC* tduLc, const uint8_t* data, boo if (m_p25->m_network == nullptr) return; + if (m_p25->m_network->disallowUnitToUnit() && (tduLc->getLCO() == LCO::PRIVATE || tduLc->getLCO() == LCO::PRIVATE_EXT)) + return; + if (m_p25->m_rfTimeoutTimer.isRunning() && m_p25->m_rfTimeoutTimer.hasExpired()) return; diff --git a/src/host/p25/packet/Voice.cpp b/src/host/p25/packet/Voice.cpp index dfb3800b..2433a8a6 100644 --- a/src/host/p25/packet/Voice.cpp +++ b/src/host/p25/packet/Voice.cpp @@ -1489,6 +1489,9 @@ void Voice::writeNetwork(const uint8_t *data, defines::DUID::E duid, defines::Fr if (m_p25->m_network == nullptr) return; + if (m_p25->m_network->disallowUnitToUnit() && !m_rfLC.getGroup()) + return; + if (m_p25->m_rfTimeoutTimer.isRunning() && m_p25->m_rfTimeoutTimer.hasExpired()) return; diff --git a/src/host/p25/phase2/Control.cpp b/src/host/p25/phase2/Control.cpp index fff63ab0..46aa0e89 100644 --- a/src/host/p25/phase2/Control.cpp +++ b/src/host/p25/phase2/Control.cpp @@ -292,6 +292,10 @@ bool Control::writeNetwork(Slot* slot, const uint8_t* data, uint32_t length) if (m_network == nullptr || slot == nullptr || data == nullptr) return true; + if (m_network->disallowUnitToUnit() && (slot->m_control.getLCO() == defines::P2_MAC_MCO::PRIVATE || + (slot->m_controlByte & network::NET_CTRL_U2U) == network::NET_CTRL_U2U)) + return true; + const bool ret = m_network->writeP25P2(slot->m_control, slot->m_duid, (uint8_t)slot->m_slotNo, slot->m_rfScrambleOffset, data, slot->m_controlByte); if (!ret) LogWarning(LOG_NET, "P25 Phase 2 Slot %u, failed to write network frame, duid = $%02X", slot->m_slotNo + 1U, (uint8_t)slot->m_duid);