From 8dd504adea4c46b822e052f2e7fb64f75ddd64d9 Mon Sep 17 00:00:00 2001 From: Bryan Biedenkapp Date: Sun, 6 Apr 2025 13:10:47 -0400 Subject: [PATCH] add support to enable/disable CC message stream debug when a protocol debug is enabled; correct some bad handling of the MESSAGE_TYPE_REG NXDN command; --- src/common/nxdn/lc/rcch/MESSAGE_TYPE_REG.cpp | 20 +++++++---- src/host/dmr/Control.cpp | 3 ++ src/host/dmr/Slot.cpp | 7 ++++ src/host/dmr/Slot.h | 7 ++++ src/host/nxdn/Control.cpp | 7 ++++ src/host/nxdn/Control.h | 1 + src/host/nxdn/packet/ControlSignaling.cpp | 38 ++++++++++++++------ src/host/nxdn/packet/ControlSignaling.h | 3 +- src/host/p25/Control.cpp | 6 ++++ src/host/p25/Control.h | 1 + src/host/p25/packet/ControlSignaling.cpp | 6 ++++ 11 files changed, 82 insertions(+), 17 deletions(-) diff --git a/src/common/nxdn/lc/rcch/MESSAGE_TYPE_REG.cpp b/src/common/nxdn/lc/rcch/MESSAGE_TYPE_REG.cpp index 51fabff6..b9a2679d 100644 --- a/src/common/nxdn/lc/rcch/MESSAGE_TYPE_REG.cpp +++ b/src/common/nxdn/lc/rcch/MESSAGE_TYPE_REG.cpp @@ -4,7 +4,7 @@ * GPLv2 Open Source. Use is subject to license terms. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * - * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL + * Copyright (C) 2022,2024,2025 Bryan Biedenkapp, N2PLL * */ #include "Defines.h" @@ -38,9 +38,12 @@ void MESSAGE_TYPE_REG::decode(const uint8_t* data, uint32_t length, uint32_t off RCCH::decode(data, rcch, length, offset); m_regOption = rcch[1U] >> 3; // Registration Option - m_locId = (uint16_t)((rcch[2U] << 8) | rcch[3U]) & 0xFFFFU; // Location ID + + m_locId = ((rcch[1U] & 0x07U) << 3) + ((rcch[2U] & 0xFFU) << 8U) + // Location ID + (rcch[3U] & 0xFFU); // ... + m_srcId = (uint16_t)((rcch[4U] << 8) | rcch[5U]) & 0xFFFFU; // Source Radio Address - m_dstId = (uint16_t)((rcch[6U] << 8) | rcch[7U]) & 0xFFFFU; // Target Radio Address + m_dstId = (uint16_t)((rcch[6U] << 8) | rcch[7U]) & 0xFFFFU; // Talkgroup Address // bryanb: maybe process subscriber type? (byte 8 and 9) m_version = rcch[10U]; // Version } @@ -53,11 +56,16 @@ void MESSAGE_TYPE_REG::encode(uint8_t* data, uint32_t length, uint32_t offset) uint8_t rcch[NXDN_RCCH_LC_LENGTH_BYTES + 4U]; ::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U); - rcch[2U] = (m_siteData.locId() >> 8) & 0xFFU; // ... - rcch[3U] = (m_siteData.locId() >> 0) & 0xFFU; // ... + rcch[1U] = (m_regOption << 3) + // Registration Option + (m_siteData.locId() >> 22U) & 0x03U; // Location ID + + uint16_t systemCode = (m_siteData.locId() >> 12U) << 7U; + rcch[2U] = (systemCode >> 8U) & 0x03U; // ... + rcch[3U] = systemCode & 0xFFU; // ... + rcch[4U] = (m_srcId >> 8U) & 0xFFU; // Source Radio Address rcch[5U] = (m_srcId >> 0U) & 0xFFU; // ... - rcch[6U] = (m_dstId >> 8U) & 0xFFU; // Target Radio Address + rcch[6U] = (m_dstId >> 8U) & 0xFFU; // Talkgroup Address rcch[7U] = (m_dstId >> 0U) & 0xFFU; // ... rcch[8U] = m_causeRsp; // Cause (MM) diff --git a/src/host/dmr/Control.cpp b/src/host/dmr/Control.cpp index e6c21b89..f2a96377 100644 --- a/src/host/dmr/Control.cpp +++ b/src/host/dmr/Control.cpp @@ -112,6 +112,7 @@ void Control::setOptions(yaml::Node& conf, bool supervisor, ::lookups::VoiceChDa else { dedicatedTSCC = false; } + bool ccDebug = control["debug"].as(false); Slot::setSiteData(controlChData, netId, siteId, channelId, channelNo, dedicatedTSCC); Slot::setAlohaConfig(nRandWait, backOff); @@ -125,11 +126,13 @@ void Control::setOptions(yaml::Node& conf, bool supervisor, ::lookups::VoiceChDa m_slot1->setTSCC(enableTSCC, dedicatedTSCC); m_slot1->setSupervisor(m_supervisor); m_slot1->setDisableSourceIDGrantCheck(disableGrantSourceIdCheck); + m_slot1->setCCDebug(ccDebug); break; case 2U: m_slot2->setTSCC(enableTSCC, dedicatedTSCC); m_slot2->setSupervisor(m_supervisor); m_slot2->setDisableSourceIDGrantCheck(disableGrantSourceIdCheck); + m_slot2->setCCDebug(ccDebug); break; default: LogError(LOG_DMR, "DMR, invalid slot, TSCC disabled, slotNo = %u", m_tsccSlotNo); diff --git a/src/host/dmr/Slot.cpp b/src/host/dmr/Slot.cpp index 425613ad..a34186b3 100644 --- a/src/host/dmr/Slot.cpp +++ b/src/host/dmr/Slot.cpp @@ -164,6 +164,7 @@ Slot::Slot(uint32_t slotNo, uint32_t timeout, uint32_t tgHang, uint32_t queueSiz m_lastLateEntry(0U), m_supervisor(false), m_notifyCC(true), + m_ccDebug(debug), m_verbose(verbose), m_debug(debug) { @@ -1506,6 +1507,11 @@ void Slot::writeRF_ControlData(uint16_t frameCnt, uint8_t n) if (csbkVerbose) lc::CSBK::setVerbose(false); + // disable debug logging during control data writes (if necessary) + bool controlDebug = m_debug; + if (!m_ccDebug) + m_debug = false; + // don't add any frames if the queue is full uint8_t len = DMR_FRAME_LENGTH_BYTES + 2U; uint32_t space = m_txQueue.freeSpace(); @@ -1615,6 +1621,7 @@ void Slot::writeRF_ControlData(uint16_t frameCnt, uint8_t n) } while (i <= seqCnt); lc::CSBK::setVerbose(csbkVerbose); + m_debug = controlDebug; } /* Clears the flag indicating whether the slot is a TSCC payload slot. */ diff --git a/src/host/dmr/Slot.h b/src/host/dmr/Slot.h index 277af5c5..c8c6e3f4 100644 --- a/src/host/dmr/Slot.h +++ b/src/host/dmr/Slot.h @@ -257,6 +257,12 @@ namespace dmr */ void setNotifyCC(bool notifyCC) { m_notifyCC = notifyCC; } + /** + * @brief Sets a flag indicating whether the control message debug is enabled. + * @param enable Flag indicating whether the control message debug is enabled. + */ + void setCCDebug(bool enable) { m_ccDebug = enable; } + /** * @brief Helper to set the voice error silence threshold. * @param threshold Voice error silence threshold. @@ -420,6 +426,7 @@ namespace dmr bool m_supervisor; bool m_notifyCC; + bool m_ccDebug; bool m_verbose; bool m_debug; diff --git a/src/host/nxdn/Control.cpp b/src/host/nxdn/Control.cpp index ab2c53a8..8c93b6d3 100644 --- a/src/host/nxdn/Control.cpp +++ b/src/host/nxdn/Control.cpp @@ -115,6 +115,7 @@ Control::Control(bool authoritative, uint32_t ran, uint32_t callHang, uint32_t q m_rssiCount(0U), m_dumpRCCH(dumpRCCHData), m_notifyCC(true), + m_ccDebug(debug), m_verbose(verbose), m_debug(debug) { @@ -207,6 +208,7 @@ void Control::setOptions(yaml::Node& conf, bool supervisor, const std::string cw } m_control->m_disableGrantSrcIdCheck = control["disableGrantSourceIdCheck"].as(false); + m_ccDebug = control["debug"].as(false); m_ignoreAffiliationCheck = nxdnProtocol["ignoreAffiliationCheck"].as(false); @@ -304,6 +306,7 @@ void Control::setOptions(yaml::Node& conf, bool supervisor, const std::string cw } if (printOptions) { + LogInfo(" Site Location ID: $%04X", m_siteData.locId()); LogInfo(" Silence Threshold: %u (%.1f%%)", m_voice->m_silenceThreshold, float(m_voice->m_silenceThreshold) / 12.33F); LogInfo(" Frame Loss Threshold: %u", m_frameLossThreshold); @@ -323,6 +326,10 @@ void Control::setOptions(yaml::Node& conf, bool supervisor, const std::string cw if (disableUnitRegTimeout) { LogInfo(" Disable Unit Registration Timeout: yes"); } + + if (m_ccDebug) { + LogInfo(" Control Message Debug: yes"); + } } if (m_voice != nullptr) { diff --git a/src/host/nxdn/Control.h b/src/host/nxdn/Control.h index e8427da4..0d7320c0 100644 --- a/src/host/nxdn/Control.h +++ b/src/host/nxdn/Control.h @@ -343,6 +343,7 @@ namespace nxdn bool m_notifyCC; + bool m_ccDebug; bool m_verbose; bool m_debug; diff --git a/src/host/nxdn/packet/ControlSignaling.cpp b/src/host/nxdn/packet/ControlSignaling.cpp index 8b676ecf..2ed50e68 100644 --- a/src/host/nxdn/packet/ControlSignaling.cpp +++ b/src/host/nxdn/packet/ControlSignaling.cpp @@ -192,11 +192,11 @@ bool ControlSignaling::process(FuncChannelType::E fct, ChOption::E option, uint8 IS_SUPPORT_CONTROL_CHECK(rcch->toString(true), MessageType::RCCH_REG, srcId); if (m_verbose) { - LogMessage(LOG_RF, "NXDN, %s, srcId = %u, locId = %u", - rcch->toString(true).c_str(), srcId, rcch->getLocId()); + LogMessage(LOG_RF, "NXDN, %s, srcId = %u, locId = $%06X, regOption = $%02X", + rcch->toString(true).c_str(), srcId, rcch->getLocId(), rcch->getRegOption()); } - writeRF_Message_U_Reg_Rsp(srcId, rcch->getLocId()); + writeRF_Message_U_Reg_Rsp(srcId, dstId, rcch->getLocId()); } break; case MessageType::RCCH_GRP_REG: @@ -205,7 +205,7 @@ bool ControlSignaling::process(FuncChannelType::E fct, ChOption::E option, uint8 IS_SUPPORT_CONTROL_CHECK(rcch->toString(true), MessageType::RCCH_GRP_REG, srcId); if (m_verbose) { - LogMessage(LOG_RF, "NXDN, %s, srcId = %u, dstId = %u, locId = %u", + LogMessage(LOG_RF, "NXDN, %s, srcId = %u, dstId = %u, locId = $%06X", rcch->toString(true).c_str(), srcId, dstId, rcch->getLocId()); } @@ -388,6 +388,11 @@ void ControlSignaling::writeRF_ControlData(uint8_t frameCnt, uint8_t n, bool adj if (rcchVerbose) lc::RCCH::setVerbose(false); + // disable debug logging during control data writes (if necessary) + bool controlDebug = m_nxdn->m_debug; + if (!m_nxdn->m_ccDebug) + m_nxdn->m_debug = m_debug = false; + // don't add any frames if the queue is full uint8_t len = NXDN_FRAME_LENGTH_BYTES + 2U; uint32_t space = m_nxdn->m_txQueue.freeSpace(); @@ -417,6 +422,7 @@ void ControlSignaling::writeRF_ControlData(uint8_t frameCnt, uint8_t n, bool adj } while (i <= seqCnt); lc::RCCH::setVerbose(rcchVerbose); + m_nxdn->m_debug = m_debug = controlDebug; } /* Helper to write a grant packet. */ @@ -661,7 +667,7 @@ bool ControlSignaling::writeRF_Message_Grp_Reg_Rsp(uint32_t srcId, uint32_t dstI // validate the location ID if (locId != m_nxdn->m_siteData.locId()) { - LogWarning(LOG_RF, "NXDN, %s denial, LOCID rejection, locId = $%04X", rcch->toString().c_str(), locId); + LogWarning(LOG_RF, "NXDN, %s denial, LOCID rejection, locId = $%06X", rcch->toString().c_str(), locId); ::ActivityLog("NXDN", true, "group affiliation request from %u denied", srcId); rcch->setCauseResponse(CauseResponse::MM_REG_FAILED); } @@ -711,14 +717,14 @@ bool ControlSignaling::writeRF_Message_Grp_Reg_Rsp(uint32_t srcId, uint32_t dstI /* Helper to write a unit registration response packet. */ -void ControlSignaling::writeRF_Message_U_Reg_Rsp(uint32_t srcId, uint32_t locId) +void ControlSignaling::writeRF_Message_U_Reg_Rsp(uint32_t srcId, uint32_t dstId, uint32_t locId) { std::unique_ptr rcch = std::make_unique(); rcch->setCauseResponse(CauseResponse::MM_REG_ACCEPTED); // validate the location ID - if (locId != m_nxdn->m_siteData.locId()) { - LogWarning(LOG_RF, "NXDN, %s denial, LOCID rejection, locId = $%04X", rcch->toString().c_str(), locId); + if (locId != ((m_nxdn->m_siteData.locId() >> 12U) << 7U)) { + LogWarning(LOG_RF, "NXDN, %s denial, LOCID rejection, locId = $%06X", rcch->toString().c_str(), locId); ::ActivityLog("NXDN", true, "unit registration request from %u denied", srcId); rcch->setCauseResponse(CauseResponse::MM_REG_FAILED); } @@ -730,9 +736,21 @@ void ControlSignaling::writeRF_Message_U_Reg_Rsp(uint32_t srcId, uint32_t locId) rcch->setCauseResponse(CauseResponse::MM_REG_FAILED); } + // validate the talkgroup ID + if (dstId == 0U) { + LogWarning(LOG_RF, "NXDN, %s, TGID 0, dstId = %u", rcch->toString().c_str(), dstId); + } + else { + if (!acl::AccessControl::validateTGId(dstId)) { + LogWarning(LOG_RF, "NXDN, %s denial, TGID rejection, dstId = %u", rcch->toString().c_str(), dstId); + ::ActivityLog("NXDN", true, "unit registration request from %u to %s %u denied", srcId, "TG ", dstId); + rcch->setCauseResponse(CauseResponse::MM_REG_FAILED); + } + } + if (rcch->getCauseResponse() == CauseResponse::MM_REG_ACCEPTED) { if (m_verbose) { - LogMessage(LOG_RF, "NXDN, %s, srcId = %u, locId = %u", + LogMessage(LOG_RF, "NXDN, %s, srcId = %u, locId = $%06X", rcch->toString().c_str(), srcId, locId); } @@ -748,7 +766,7 @@ void ControlSignaling::writeRF_Message_U_Reg_Rsp(uint32_t srcId, uint32_t locId) } rcch->setSrcId(srcId); - rcch->setDstId(srcId); + rcch->setDstId(dstId); writeRF_Message_Imm(rcch.get(), true); } diff --git a/src/host/nxdn/packet/ControlSignaling.h b/src/host/nxdn/packet/ControlSignaling.h index 063e1d75..67fec18a 100644 --- a/src/host/nxdn/packet/ControlSignaling.h +++ b/src/host/nxdn/packet/ControlSignaling.h @@ -168,9 +168,10 @@ namespace nxdn /** * @brief Helper to write a unit registration response packet. * @param srcId Source Radio ID. + * @param dstId Destination ID. * @param locId Location ID. */ - void writeRF_Message_U_Reg_Rsp(uint32_t srcId, uint32_t locId); + void writeRF_Message_U_Reg_Rsp(uint32_t srcId, uint32_t dstId, uint32_t locId); /** * @brief Helper to write a CC SITE_INFO broadcast packet on the RF interface. diff --git a/src/host/p25/Control.cpp b/src/host/p25/Control.cpp index ff532ac3..52a26b03 100644 --- a/src/host/p25/Control.cpp +++ b/src/host/p25/Control.cpp @@ -127,6 +127,7 @@ Control::Control(bool authoritative, uint32_t nac, uint32_t callHang, uint32_t q m_aveRSSI(0U), m_rssiCount(0U), m_notifyCC(true), + m_ccDebug(debug), m_verbose(verbose), m_debug(debug) { @@ -310,6 +311,7 @@ void Control::setOptions(yaml::Node& conf, bool supervisor, const std::string cw m_control->m_ctrlTimeDateAnn = control["enableTimeDateAnn"].as(false); m_control->m_redundantImmediate = control["redundantImmediate"].as(true); m_control->m_redundantGrant = control["redundantGrantTransmit"].as(false); + m_ccDebug = control["debug"].as(false); m_allowExplicitSourceId = p25Protocol["allowExplicitSourceId"].as(true); m_convNetGrantDemand = p25Protocol["convNetGrantDemand"].as(false); @@ -515,6 +517,10 @@ void Control::setOptions(yaml::Node& conf, bool supervisor, const std::string cw if (m_control->m_redundantGrant) { LogInfo(" Redundant Grant Transmit: yes"); } + + if (m_ccDebug) { + LogInfo(" Control Message Debug: yes"); + } } // are we overriding the NAC for split NAC operations? diff --git a/src/host/p25/Control.h b/src/host/p25/Control.h index 0cd0c790..18f7e524 100644 --- a/src/host/p25/Control.h +++ b/src/host/p25/Control.h @@ -380,6 +380,7 @@ namespace p25 bool m_notifyCC; + bool m_ccDebug; bool m_verbose; bool m_debug; diff --git a/src/host/p25/packet/ControlSignaling.cpp b/src/host/p25/packet/ControlSignaling.cpp index 61ecb18c..abfaf5a4 100644 --- a/src/host/p25/packet/ControlSignaling.cpp +++ b/src/host/p25/packet/ControlSignaling.cpp @@ -1759,6 +1759,11 @@ void ControlSignaling::writeRF_ControlData(uint8_t frameCnt, uint8_t n, bool adj if (tsbkVerbose) lc::TSBK::setVerbose(false); + // disable debug logging during control data writes (if necessary) + bool controlDebug = m_p25->m_debug; + if (!m_p25->m_ccDebug) + m_p25->m_debug = m_debug = false; + if (m_convFallback) { bool fallbackTx = (frameCnt % 253U) == 0U; if (fallbackTx && n == 8U) { @@ -1901,6 +1906,7 @@ void ControlSignaling::writeRF_ControlData(uint8_t frameCnt, uint8_t n, bool adj } lc::TSBK::setVerbose(tsbkVerbose); + m_p25->m_debug = m_debug = controlDebug; } /* Helper to generate the given control TSBK into the TSDU frame queue. */