add initial support to drop inbound network U2U calls at the host;

pull/134/head
Bryan Biedenkapp 4 days ago
parent b72823cfd7
commit d357736f24

@ -106,6 +106,9 @@ network:
# Maximum allowable DMR network jitter.
jitter: 360
# Flag indicating whether inbound unit-to-unit calls from the network will be discarded.
disallowUnitToUnit: false
# Flag indicating whether DMR slot 1 traffic will be passed.
slot1: true
# Flag indicating whether DMR slot 2 traffic will be passed.

@ -30,9 +30,10 @@ using namespace network;
Network::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,
bool allowActivityTransfer, bool allowDiagnosticTransfer, bool updateLookup, bool saveLookup) :
bool allowActivityTransfer, bool allowDiagnosticTransfer, bool updateLookup, bool saveLookup, bool disallowUnitToUnit) :
BaseNetwork(peerId, duplex, debug, slot1, slot2, allowActivityTransfer, allowDiagnosticTransfer, localPort),
m_pktLastSeq(0U),
m_disallowUnitToUnit(disallowUnitToUnit),
m_address(address),
m_port(port),
m_configuredAddress(address),

@ -163,10 +163,11 @@ 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.
*/
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,
bool allowActivityTransfer, bool allowDiagnosticTransfer, bool updateLookup, bool saveLookup);
bool allowActivityTransfer, bool allowDiagnosticTransfer, bool updateLookup, bool saveLookup, bool disallowUnitToUnit = false);
/**
* @brief Finalizes a instance of the Network class.
*/
@ -332,6 +333,11 @@ namespace network
*/
DECLARE_RO_PROPERTY_PLAIN(uint16_t, pktLastSeq);
/**
* @brief Flag indicating that inbound unit-to-unit traffic is discarded.
*/
DECLARE_RO_PROPERTY_PLAIN(bool, disallowUnitToUnit);
protected:
std::string m_address;
uint16_t m_port;

@ -870,6 +870,7 @@ bool Host::createNetwork()
bool allowStatusTransfer = networkConf["allowStatusTransfer"].as<bool>(true);
bool updateLookup = networkConf["updateLookups"].as<bool>(false);
bool saveLookup = networkConf["saveLookups"].as<bool>(false);
bool disallowUnitToUnit = networkConf["disallowUnitToUnit"].as<bool>(false);
bool packetDump = networkConf["packetDump"].as<bool>(false);
bool debug = networkConf["debug"].as<bool>(false);
@ -995,6 +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(" Encrypted: %s", encrypted ? "yes" : "no");
LogInfo(" KMF Encrypted: %s", kmfEncrypted ? "yes" : "no");
@ -1024,7 +1026,7 @@ bool Host::createNetwork()
// initialize networking
if (netEnable) {
m_network = new Network(address, port, local, id, password, m_duplex, debug, m_dmrEnabled, m_p25Enabled, m_nxdnEnabled, false, slot1, slot2,
allowActivityTransfer, allowDiagnosticTransfer, updateLookup, saveLookup);
allowActivityTransfer, allowDiagnosticTransfer, updateLookup, saveLookup, disallowUnitToUnit);
m_network->setPacketDump(packetDump);
m_network->setLookups(m_ridLookup, m_tidLookup);

@ -459,6 +459,10 @@ void Slot::processNetwork(const data::NetData& dmrData)
bool unitToUnit = (dmrData.getControl() & network::NET_CTRL_U2U) == network::NET_CTRL_U2U;
if (grantDemand) {
if (s_network->disallowUnitToUnit() && unitToUnit) {
break;
}
// validate source RID
if (!acl::AccessControl::validateSrcId(dmrData.getSrcId())) {
break;

@ -441,6 +441,12 @@ void Data::processNetwork(const data::NetData& dmrData)
uint32_t srcId = m_netDataHeader.getSrcId();
uint32_t dstId = m_netDataHeader.getDstId();
if (m_slot->s_network->disallowUnitToUnit() && !gi) {
LogWarning(LOG_NET, "DMR Slot %u, rejecting network individual data call, srcId = %u, dstId = %u",
m_slot->m_slotNo, srcId, dstId);
return;
}
if (!m_slot->s_authoritative && m_slot->m_permittedDstId != dstId) {
return;
}

@ -781,6 +781,12 @@ void Voice::processNetwork(const data::NetData& dmrData)
uint32_t dstId = lc->getDstId();
FLCO::E flco = lc->getFLCO();
if (m_slot->s_network->disallowUnitToUnit() && flco == FLCO::PRIVATE) {
LogWarning(LOG_NET, "DMR Slot %u, rejecting network unit-to-unit voice call, srcId = %u, dstId = %u",
m_slot->m_slotNo, srcId, dstId);
return;
}
CHECK_NET_AUTHORITATIVE(dstId);
if (checkNetTrafficCollision(dstId))
@ -871,6 +877,10 @@ void Voice::processNetwork(const data::NetData& dmrData)
if (m_slot->m_netState != RS_NET_AUDIO) {
std::unique_ptr<lc::LC> lc = std::make_unique<lc::LC>(dmrData.getFLCO(), dmrData.getSrcId(), dmrData.getDstId());
if (m_slot->s_network->disallowUnitToUnit() && lc->getFLCO() == FLCO::PRIVATE) {
return;
}
uint32_t srcId = lc->getSrcId();
uint32_t dstId = lc->getDstId();
@ -978,6 +988,10 @@ void Voice::processNetwork(const data::NetData& dmrData)
if (m_slot->m_netState == RS_NET_IDLE) {
std::unique_ptr<lc::LC> lc = std::make_unique<lc::LC>(dmrData.getFLCO(), dmrData.getSrcId(), dmrData.getDstId());
if (m_slot->s_network->disallowUnitToUnit() && lc->getFLCO() == FLCO::PRIVATE) {
return;
}
uint32_t dstId = lc->getDstId();
uint32_t srcId = lc->getSrcId();

@ -289,6 +289,23 @@ bool ControlSignaling::processNetwork(FuncChannelType::E fct, ChOption::E option
uint16_t srcId = rcch->getSrcId();
uint16_t dstId = rcch->getDstId();
if (m_nxdn->m_network->disallowUnitToUnit()) {
switch (rcch->getMessageType()) {
case MessageType::RTCH_VCALL:
if (!rcch->getGroup()) {
LogWarning(LOG_NET, "NXDN, rejecting network unit-to-unit call request, srcId = %u, dstId = %u",
srcId, dstId);
return false;
}
break;
case MessageType::RCCH_VCALL_REC:
case MessageType::RCCH_VCALL_CONN:
return false;
default:
break;
}
}
// handle standard NXDN message opcodes
switch (rcch->getMessageType()) {
case MessageType::RTCH_VCALL:

@ -240,6 +240,12 @@ bool Data::processNetwork(ChOption::E option, lc::RTCH& netLC, uint8_t* data, ui
uint16_t srcId = lc.getSrcId();
bool group = lc.getGroup();
if (m_nxdn->m_network->disallowUnitToUnit() && !group) {
LogWarning(LOG_NET, "NXDN, rejecting network individual data call, srcId = %u, dstId = %u",
srcId, dstId);
return false;
}
// overwrite the destination ID if the network message header and
// decoded network LC data don't agree (this can happen if the network is dynamically
// altering the destination ID in-flight)

@ -694,6 +694,12 @@ bool Voice::processNetwork(FuncChannelType::E fct, ChOption::E option, lc::RTCH&
bool group = lc.getGroup();
bool encrypted = lc.getEncrypted();
if (m_nxdn->m_network->disallowUnitToUnit() && !group) {
LogWarning(LOG_NET, "NXDN, rejecting network unit-to-unit voice call, srcId = %u, dstId = %u",
srcId, dstId);
return false;
}
// overwrite the destination ID if the network message header and
// decoded network LC data don't agree (this can happen if the network is dynamically
// altering the destination ID in-flight)

@ -107,6 +107,7 @@ Control::Control(bool authoritative, uint32_t nac, uint32_t callHang, uint32_t q
m_netState(RS_NET_IDLE),
m_netLastDstId(0U),
m_netLastSrcId(0U),
m_netRejectedU2UStream(false),
m_permittedDstId(0U),
m_permittedSrcId(0U),
m_permittedU2U(false),
@ -1634,6 +1635,38 @@ void Control::processNetwork()
control.setNetId(netId);
control.setSysId(sysId);
if (m_network->disallowUnitToUnit()) {
const bool privateCall = lco == LCO::PRIVATE || lco == LCO::PRIVATE_EXT;
const bool voiceFrame = duid == DUID::HDU || duid == DUID::LDU1 || duid == DUID::LDU2;
const bool callEnd = duid == DUID::TDU || duid == DUID::TDULC;
// continuation frames such as LDU2 do not carry a voice-user LCO, so
// retain rejection state until call end or a fresh group call header
if (m_netRejectedU2UStream) {
const bool newGroupCall = (duid == DUID::HDU || duid == DUID::LDU1) && !privateCall && !unitToUnit;
if (newGroupCall) {
m_netRejectedU2UStream = false;
}
else if (voiceFrame || callEnd) {
if (callEnd)
m_netRejectedU2UStream = false;
return;
}
}
// reject network unit-to-unit calls if either a private call or unit-to-unit call is detected
if (privateCall || unitToUnit) {
if (voiceFrame) {
m_netRejectedU2UStream = true;
m_network->resetP25();
}
LogWarning(LOG_NET, "P25, rejecting network unit-to-unit call stream, lco = $%02X, srcId = %u, dstId = %u",
lco, srcId, dstId);
return;
}
}
lsd.setLSD1(lsd1);
lsd.setLSD2(lsd2);

@ -365,6 +365,7 @@ namespace p25
RPT_NET_STATE m_netState;
uint32_t m_netLastDstId;
uint32_t m_netLastSrcId;
bool m_netRejectedU2UStream;
uint32_t m_permittedDstId;
uint32_t m_permittedSrcId;

@ -872,6 +872,18 @@ bool ControlSignaling::processNetwork(uint8_t* data, uint32_t len, lc::LC& contr
return false;
}
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:
LogWarning(LOG_NET, P25_TSDU_STR ", rejecting network unit-to-unit signaling, lco = $%02X", tsbk->getLCO());
return false;
default:
break;
}
}
// handle updating internal adjacent site information
if (tsbk->getLCO() == TSBKO::OSP_ADJ_STS_BCAST) {
if (!m_p25->m_enableControl) {

@ -444,6 +444,10 @@ bool Slot::processNetwork(uint8_t* data, uint32_t length, const lc::LC& control,
{
CHECK_NET_AUTHORITATIVE(control.getDstId());
if (s_network->disallowUnitToUnit() && isVoiceDUID(duid) && (controlByte & network::NET_CTRL_U2U) == network::NET_CTRL_U2U) {
return false;
}
if (m_rfState != RS_RF_LISTENING && m_netState == RS_NET_IDLE) {
++m_netMissed;
if (m_debug)
@ -1152,6 +1156,13 @@ bool Slot::processMAC(uint8_t* data, uint32_t length, defines::P2_DUID::E duid,
if (net && !m_control.decodeVCH_MACPDU_OEMI(frame, sync))
return false;
if (net && s_network->disallowUnitToUnit() &&
m_control.getLCO() == defines::P2_MAC_MCO::PRIVATE) {
LogWarning(LOG_NET, "P25 Phase 2 Slot %u, rejecting network unit-to-unit MAC PDU, srcId = %u, dstId = %u",
m_slotNo + 1U, m_control.getSrcId(), m_control.getDstId());
return false;
}
// The transport discriminator and the discriminator protected inside the
// MAC burst must agree. Do not let metadata reinterpret one coded form
// as another after the modem has classified the logical channel.

Loading…
Cancel
Save

Powered by TurnKey Linux.