diff --git a/dmr/packet/ControlSignaling.cpp b/dmr/packet/ControlSignaling.cpp index 851db1bc..eba4bae8 100644 --- a/dmr/packet/ControlSignaling.cpp +++ b/dmr/packet/ControlSignaling.cpp @@ -12,7 +12,7 @@ // /* * Copyright (C) 2015,2016,2017,2018 Jonathan Naylor, G4KLX -* Copyright (C) 2017-2022 by Bryan Biedenkapp N2PLL +* Copyright (C) 2017-2023 by Bryan Biedenkapp N2PLL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -829,6 +829,10 @@ bool ControlSignaling::writeRF_CSBK_Grant(uint32_t srcId, uint32_t dstId, uint8_ ::ActivityLog("DMR", true, "Slot %u group grant request from %u to TG %u", m_tscc->m_slotNo, srcId, dstId); } + // + // TODO TODO: Implement RCON callback for authoritative CC to trigger permit-tg + // + std::unique_ptr csbk = new_unique(CSBK_TV_GRANT); if (broadcast) csbk->setCSBKO(CSBKO_BTV_GRANT); @@ -852,6 +856,10 @@ bool ControlSignaling::writeRF_CSBK_Grant(uint32_t srcId, uint32_t dstId, uint8_ ::ActivityLog("DMR", true, "Slot %u individual grant request from %u to TG %u", m_tscc->m_slotNo, srcId, dstId); } + // + // TODO TODO: Implement RCON callback for authoritative CC to trigger permit-tg + // + std::unique_ptr csbk = new_unique(CSBK_PV_GRANT); csbk->setLogicalCh1(chNo); csbk->setSlotNo(1U); // eah? this can't be okay... diff --git a/dmr/packet/Data.cpp b/dmr/packet/Data.cpp index c4ca94d3..d7bf4767 100644 --- a/dmr/packet/Data.cpp +++ b/dmr/packet/Data.cpp @@ -12,7 +12,7 @@ // /* * Copyright (C) 2015,2016,2017,2018 Jonathan Naylor, G4KLX -* Copyright (C) 2017-2022 by Bryan Biedenkapp N2PLL +* Copyright (C) 2017-2023 by Bryan Biedenkapp N2PLL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -51,6 +51,17 @@ using namespace dmr::packet; // Macros // --------------------------------------------------------------------------- +#define CHECK_AUTHORITATIVE(_DST_ID) \ + if (!m_slot->m_authoritative && m_slot->m_permittedDstId != dstId) { \ + LogWarning(LOG_RF, "[NON-AUTHORITATIVE] Ignoring RF traffic, destination not permitted!"); \ + return false; \ + } + +#define CHECK_NET_AUTHORITATIVE(_DST_ID) \ + if (!m_slot->m_authoritative && m_slot->m_permittedDstId != dstId) { \ + return; \ + } + // Don't process RF frames if the network isn't in a idle state. #define CHECK_TRAFFIC_COLLISION(_DST_ID) \ if (m_slot->m_netState != RS_NET_IDLE && _DST_ID == m_slot->m_netLastDstId) { \ @@ -161,6 +172,7 @@ bool Data::process(uint8_t* data, uint32_t len) uint32_t srcId = dataHeader->getSrcId(); uint32_t dstId = dataHeader->getDstId(); + CHECK_AUTHORITATIVE(dstId); CHECK_TRAFFIC_COLLISION(dstId); // validate the source RID @@ -378,6 +390,7 @@ void Data::processNetwork(const data::Data& dmrData) uint32_t srcId = dataHeader->getSrcId(); uint32_t dstId = dataHeader->getDstId(); + CHECK_NET_AUTHORITATIVE(dstId); CHECK_TG_HANG(dstId); m_slot->m_netFrames = dataHeader->getBlocks(); diff --git a/dmr/packet/Voice.cpp b/dmr/packet/Voice.cpp index 4c840f2b..ec50d32f 100644 --- a/dmr/packet/Voice.cpp +++ b/dmr/packet/Voice.cpp @@ -12,7 +12,7 @@ // /* * Copyright (C) 2015,2016,2017,2018 Jonathan Naylor, G4KLX -* Copyright (C) 2017-2022 by Bryan Biedenkapp N2PLL +* Copyright (C) 2017-2023 by Bryan Biedenkapp N2PLL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -53,6 +53,17 @@ using namespace dmr::packet; // Macros // --------------------------------------------------------------------------- +#define CHECK_AUTHORITATIVE(_DST_ID) \ + if (!m_slot->m_authoritative && m_slot->m_permittedDstId != dstId) { \ + LogWarning(LOG_RF, "[NON-AUTHORITATIVE] Ignoring RF traffic, destination not permitted!"); \ + return false; \ + } + +#define CHECK_NET_AUTHORITATIVE(_DST_ID) \ + if (!m_slot->m_authoritative && m_slot->m_permittedDstId != dstId) { \ + return; \ + } + #define CHECK_TRAFFIC_COLLISION(_DST_ID) \ if (m_slot->m_netState != RS_NET_IDLE && _DST_ID == m_slot->m_netLastDstId) { \ LogWarning(LOG_RF, "DMR Slot %u, Traffic collision detect, preempting new RF traffic to existing network traffic!", m_slot->m_slotNo); \ @@ -103,6 +114,7 @@ bool Voice::process(uint8_t* data, uint32_t len) uint32_t dstId = lc->getDstId(); uint8_t flco = lc->getFLCO(); + CHECK_AUTHORITATIVE(dstId); CHECK_TRAFFIC_COLLISION(dstId); // validate source RID @@ -477,6 +489,7 @@ bool Voice::process(uint8_t* data, uint32_t len) uint32_t dstId = lc->getDstId(); uint8_t flco = lc->getFLCO(); + CHECK_AUTHORITATIVE(dstId); CHECK_TRAFFIC_COLLISION(dstId); // validate the source RID @@ -638,6 +651,7 @@ void Voice::processNetwork(const data::Data& dmrData) uint32_t dstId = lc->getDstId(); uint8_t flco = lc->getFLCO(); + CHECK_NET_AUTHORITATIVE(dstId); CHECK_TG_HANG(dstId); if (dstId != dmrData.getDstId() || srcId != dmrData.getSrcId() || flco != dmrData.getFLCO()) @@ -721,6 +735,7 @@ void Voice::processNetwork(const data::Data& dmrData) uint32_t srcId = lc->getSrcId(); uint32_t dstId = lc->getDstId(); + CHECK_NET_AUTHORITATIVE(dstId); CHECK_TG_HANG(dstId); m_slot->m_netLC = std::move(lc); @@ -816,6 +831,8 @@ void Voice::processNetwork(const data::Data& dmrData) uint32_t dstId = lc->getDstId(); uint32_t srcId = lc->getSrcId(); + CHECK_NET_AUTHORITATIVE(dstId); + m_slot->m_netLC = std::move(lc); // The standby LC data diff --git a/nxdn/packet/Trunk.cpp b/nxdn/packet/Trunk.cpp index 51118aac..f5290e6c 100644 --- a/nxdn/packet/Trunk.cpp +++ b/nxdn/packet/Trunk.cpp @@ -11,7 +11,7 @@ // Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0) // /* -* Copyright (C) 2022 by Bryan Biedenkapp N2PLL +* Copyright (C) 2022-2023 by Bryan Biedenkapp N2PLL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -508,6 +508,10 @@ bool Trunk::writeRF_Message_Grant(uint32_t srcId, uint32_t dstId, uint8_t servic } } + // + // TODO TODO: Implement RCON callback for authoritative CC to trigger permit-tg + // + std::unique_ptr rcch = new_unique(rcch::MESSAGE_TYPE_VCALL_CONN); rcch->setMessageType(RTCH_MESSAGE_TYPE_VCALL); rcch->setGrpVchNo(chNo); diff --git a/nxdn/packet/Voice.cpp b/nxdn/packet/Voice.cpp index 23ecf0e5..29b54427 100644 --- a/nxdn/packet/Voice.cpp +++ b/nxdn/packet/Voice.cpp @@ -12,7 +12,7 @@ // /* * Copyright (C) 2015-2020 by Jonathan Naylor G4KLX -* Copyright (C) 2022 by Bryan Biedenkapp N2PLL +* Copyright (C) 2022-2023 by Bryan Biedenkapp N2PLL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -218,6 +218,17 @@ bool Voice::process(uint8_t fct, uint8_t option, uint8_t* data, uint32_t len) bool group = lc.getGroup(); bool encrypted = lc.getEncrypted(); + // don't process RF frames if this modem isn't authoritative + if (!m_nxdn->m_authoritative && m_nxdn->m_permittedDstId != dstId) { + if (m_nxdn->m_rfState != RS_RF_AUDIO) { + LogWarning(LOG_RF, "[NON-AUTHORITATIVE] Ignoring RF traffic, destination not permitted!"); + m_nxdn->m_rfState = RS_RF_LISTENING; + m_nxdn->m_rfMask = 0x00U; + m_nxdn->m_rfLC.reset(); + return false; + } + } + uint8_t type = lc.getMessageType(); if (type == RTCH_MESSAGE_TYPE_TX_REL) { if (m_nxdn->m_rfState != RS_RF_AUDIO) { @@ -650,6 +661,18 @@ bool Voice::processNetwork(uint8_t fct, uint8_t option, lc::RTCH& netLC, uint8_t bool group = lc.getGroup(); bool encrypted = lc.getEncrypted(); + // don't process network frames if this modem isn't authoritative + if (!m_nxdn->m_authoritative && m_nxdn->m_permittedDstId != dstId) { + if (m_nxdn->m_netState != RS_NET_AUDIO) { + // bryanb: do we want to log this condition? + //LogWarning(LOG_NET, "[NON-AUTHORITATIVE] Ignoring network traffic, destination not permitted!"); + m_nxdn->m_netState = RS_NET_IDLE; + m_nxdn->m_netMask = 0x00U; + m_nxdn->m_netLC.reset(); + return false; + } + } + uint8_t type = lc.getMessageType(); if (type == RTCH_MESSAGE_TYPE_TX_REL) { if (m_nxdn->m_netState != RS_NET_AUDIO) { diff --git a/p25/packet/Trunk.cpp b/p25/packet/Trunk.cpp index 88069c4b..7df44fb8 100644 --- a/p25/packet/Trunk.cpp +++ b/p25/packet/Trunk.cpp @@ -7,7 +7,7 @@ * */ /* -* Copyright (C) 2017-2022 by Bryan Biedenkapp N2PLL +* Copyright (C) 2017-2023 by Bryan Biedenkapp N2PLL * Copyright (C) 2022 by Jason-UWU - TIME_DATE_ANN & RAD_MON_CMD * * This program is free software; you can redistribute it and/or modify @@ -2233,6 +2233,10 @@ bool Trunk::writeRF_TSDU_Grant(uint32_t srcId, uint32_t dstId, uint8_t serviceOp ::ActivityLog("P25", true, "group grant request from %u to TG %u", srcId, dstId); } + // + // TODO TODO: Implement RCON callback for authoritative CC to trigger permit-tg + // + std::unique_ptr iosp = new_unique(IOSP_GRP_VCH); iosp->setMFId(m_lastMFID); iosp->setSrcId(srcId); @@ -2255,6 +2259,10 @@ bool Trunk::writeRF_TSDU_Grant(uint32_t srcId, uint32_t dstId, uint8_t serviceOp ::ActivityLog("P25", true, "unit-to-unit grant request from %u to %u", srcId, dstId); } + // + // TODO TODO: Implement RCON callback for authoritative CC to trigger permit-tg + // + std::unique_ptr iosp = new_unique(IOSP_UU_VCH); iosp->setMFId(m_lastMFID); iosp->setSrcId(srcId); diff --git a/p25/packet/Voice.cpp b/p25/packet/Voice.cpp index f71191d0..4a9c3c57 100644 --- a/p25/packet/Voice.cpp +++ b/p25/packet/Voice.cpp @@ -12,7 +12,7 @@ // /* * Copyright (C) 2016,2017,2018 by Jonathan Naylor G4KLX -* Copyright (C) 2017-2022 by Bryan Biedenkapp N2PLL +* Copyright (C) 2017-2023 by Bryan Biedenkapp N2PLL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -167,6 +167,13 @@ bool Voice::process(uint8_t* data, uint32_t len) LogMessage(LOG_RF, P25_HDU_STR ", HDU_BSDWNACT, dstId = %u, algo = $%02X, kid = $%04X", lc.getDstId(), lc.getAlgId(), lc.getKId()); } + // don't process RF frames if this modem isn't authoritative + if (!m_p25->m_authoritative && m_p25->m_permittedDstId != lc.getDstId()) { + LogWarning(LOG_RF, "[NON-AUTHORITATIVE] Ignoring RF traffic, destination not permitted!"); + resetRF(); + return false; + } + // don't process RF frames if the network isn't in a idle state and the RF destination is the network destination if (m_p25->m_netState != RS_NET_IDLE && lc.getDstId() == m_p25->m_netLastDstId) { LogWarning(LOG_RF, "Traffic collision detect, preempting new RF traffic to existing network traffic!"); @@ -231,6 +238,13 @@ bool Voice::process(uint8_t* data, uint32_t len) alreadyDecoded = true; + // don't process RF frames if this modem isn't authoritative + if (!m_p25->m_authoritative && m_p25->m_permittedDstId != lc.getDstId()) { + LogWarning(LOG_RF, "[NON-AUTHORITATIVE] Ignoring RF traffic, destination not permitted!"); + resetRF(); + return false; + } + // don't process RF frames if the network isn't in a idle state and the RF destination is the network destination if (m_p25->m_netState != RS_NET_IDLE && dstId == m_p25->m_netLastDstId) { LogWarning(LOG_RF, "Traffic collision detect, preempting new RF traffic to existing network traffic!"); @@ -1066,6 +1080,14 @@ void Voice::writeNet_LDU1() LogWarning(LOG_NET, P25_HDU_STR ", last LDU1 LC has bad data, srcId = 0"); } + // don't process network frames if this modem isn't authoritative + if (!m_p25->m_authoritative && m_p25->m_permittedDstId != dstId) { + // bryanb: do we want to log this condition? + //LogWarning(LOG_NET, "[NON-AUTHORITATIVE] Ignoring network traffic, destination not permitted!"); + resetNet(); + return; + } + // don't process network frames if the destination ID's don't match and the network TG hang timer is running if (m_p25->m_rfLastDstId != 0U) { if (m_p25->m_rfLastDstId != dstId && (m_p25->m_rfTGHang.isRunning() && !m_p25->m_rfTGHang.hasExpired())) {