2016-07-10 10:47:23 +00:00
/*
* 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
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
*/
# include "DMRAccessControl.h"
2016-07-10 16:32:00 +00:00
# include "Log.h"
2016-07-10 10:47:23 +00:00
# include <algorithm>
# include <vector>
2016-10-13 16:46:02 +00:00
# include <cstring>
2016-07-10 10:47:23 +00:00
2016-09-17 10:07:23 +00:00
2016-11-10 18:43:54 +00:00
std : : vector < unsigned int > CDMRAccessControl : : m_dstBlackListSlot1RF ;
std : : vector < unsigned int > CDMRAccessControl : : m_dstBlackListSlot2RF ;
std : : vector < unsigned int > CDMRAccessControl : : m_dstWhiteListSlot1RF ;
std : : vector < unsigned int > CDMRAccessControl : : m_dstWhiteListSlot2RF ;
2016-07-10 20:37:11 +00:00
2016-11-10 18:43:54 +00:00
std : : vector < unsigned int > CDMRAccessControl : : m_dstBlackListSlot1NET ;
std : : vector < unsigned int > CDMRAccessControl : : m_dstBlackListSlot2NET ;
std : : vector < unsigned int > CDMRAccessControl : : m_dstWhiteListSlot1NET ;
std : : vector < unsigned int > CDMRAccessControl : : m_dstWhiteListSlot2NET ;
2016-07-10 10:47:23 +00:00
2016-11-10 18:43:54 +00:00
std : : vector < unsigned int > CDMRAccessControl : : m_srcIdBlacklist ;
2016-07-10 15:46:02 +00:00
2016-11-10 18:43:54 +00:00
std : : vector < unsigned int > CDMRAccessControl : : m_prefixes ;
2016-07-11 16:41:53 +00:00
2016-11-10 18:43:54 +00:00
bool CDMRAccessControl : : m_selfOnly = false ;
2016-07-11 16:41:53 +00:00
2016-11-10 18:43:54 +00:00
unsigned int CDMRAccessControl : : m_id = 0U ;
2016-07-10 15:46:02 +00:00
2016-11-10 18:43:54 +00:00
unsigned int CDMRAccessControl : : m_dstRewriteID [ 2 ] ;
unsigned int CDMRAccessControl : : m_srcID [ 2 ] ;
2016-09-11 11:15:03 +00:00
2016-11-10 18:43:54 +00:00
CDMRLC * CDMRAccessControl : : m_lastdmrLC ;
2016-09-19 15:35:01 +00:00
2016-11-10 18:43:54 +00:00
time_t CDMRAccessControl : : m_time [ 2 ] ;
2016-09-11 11:15:03 +00:00
2016-11-10 18:43:54 +00:00
int CDMRAccessControl : : m_callHang ;
2016-09-15 13:19:00 +00:00
2016-11-10 18:43:54 +00:00
bool CDMRAccessControl : : m_tgRewriteSlot1 ;
bool CDMRAccessControl : : m_tgRewriteSlot2 ;
bool CDMRAccessControl : : m_bmAutoRewrite ;
bool CDMRAccessControl : : m_bmRewriteReflectorVoicePrompts ;
2016-09-15 19:41:14 +00:00
2016-11-10 18:43:54 +00:00
void CDMRAccessControl : : init ( const std : : vector < unsigned int > & dstIdBlacklistSlot1RF , const std : : vector < unsigned int > & dstIdWhitelistSlot1RF , const std : : vector < unsigned int > & dstIdBlacklistSlot2RF , const std : : vector < unsigned int > & dstIdWhitelistSlot2RF , const std : : vector < unsigned int > & dstIdBlacklistSlot1NET , const std : : vector < unsigned int > & dstIdWhitelistSlot1NET , const std : : vector < unsigned int > & dstIdBlacklistSlot2NET , const std : : vector < unsigned int > & dstIdWhitelistSlot2NET , const std : : vector < unsigned int > & srcIdBlacklist , bool selfOnly , const std : : vector < unsigned int > & prefixes , unsigned int id , unsigned int callHang , bool tgRewriteSlot1 , bool tgRewriteSlot2 , bool bmAutoRewrite , bool bmRewriteReflectorVoicePrompts )
2016-07-10 10:47:23 +00:00
{
2016-10-13 16:46:02 +00:00
m_dstBlackListSlot1RF = dstIdBlacklistSlot1RF ;
m_dstWhiteListSlot1RF = dstIdWhitelistSlot1RF ;
m_dstBlackListSlot2RF = dstIdBlacklistSlot2RF ;
m_dstWhiteListSlot2RF = dstIdWhitelistSlot2RF ;
m_dstBlackListSlot1NET = dstIdBlacklistSlot1NET ;
m_dstWhiteListSlot1NET = dstIdWhitelistSlot1NET ;
m_dstBlackListSlot2NET = dstIdBlacklistSlot2NET ;
m_dstWhiteListSlot2NET = dstIdWhitelistSlot2NET ;
m_callHang = callHang ;
m_tgRewriteSlot1 = tgRewriteSlot1 ;
m_tgRewriteSlot2 = tgRewriteSlot2 ;
m_bmAutoRewrite = bmAutoRewrite ;
m_bmRewriteReflectorVoicePrompts = bmRewriteReflectorVoicePrompts ;
2016-07-10 10:47:23 +00:00
}
2016-11-10 18:43:54 +00:00
bool CDMRAccessControl : : dstIdBlacklist ( unsigned int did , unsigned int slot , bool network )
2016-07-10 10:47:23 +00:00
{
2016-07-11 16:41:53 +00:00
static std : : vector < unsigned int > blacklist ;
2016-07-10 20:37:11 +00:00
2016-07-10 10:47:23 +00:00
if ( slot = = 1U ) {
2016-07-11 16:41:53 +00:00
if ( network )
blacklist = m_dstBlackListSlot1NET ;
else
blacklist = m_dstBlackListSlot1RF ;
2016-07-10 10:47:23 +00:00
} else {
2016-07-11 16:41:53 +00:00
if ( network )
blacklist = m_dstBlackListSlot2NET ;
else
blacklist = m_dstBlackListSlot2RF ;
2016-07-10 10:47:23 +00:00
}
2016-07-11 16:41:53 +00:00
return std : : find ( blacklist . begin ( ) , blacklist . end ( ) , did ) ! = blacklist . end ( ) ;
2016-07-10 10:47:23 +00:00
}
2016-11-10 18:43:54 +00:00
bool CDMRAccessControl : : dstIdWhitelist ( unsigned int did , unsigned int slot , bool gt4k , bool network )
2016-07-10 10:47:23 +00:00
{
2016-07-10 20:37:11 +00:00
if ( network ) {
if ( slot = = 1U ) {
if ( m_dstWhiteListSlot1NET . size ( ) = = 0U )
return true ;
2016-07-10 10:47:23 +00:00
2016-07-10 20:37:11 +00:00
// No reflectors on slot1, so we only allow all IDs over 99999 unless specifically whitelisted.
2016-07-11 16:41:53 +00:00
// Allow traffic to TG0 as I think this is a special case - need to confirm
2016-07-10 20:37:11 +00:00
if ( gt4k ) {
if ( std : : find ( m_dstWhiteListSlot1NET . begin ( ) , m_dstWhiteListSlot1NET . end ( ) , did ) ! = m_dstWhiteListSlot1NET . end ( ) | | did > = 99999U | | did = = 0 )
return true ;
} else {
if ( std : : find ( m_dstWhiteListSlot1NET . begin ( ) , m_dstWhiteListSlot1NET . end ( ) , did ) ! = m_dstWhiteListSlot1NET . end ( ) | | did = = 0 )
return true ;
}
} else {
if ( m_dstWhiteListSlot2NET . size ( ) = = 0U )
return true ;
2016-07-11 16:41:53 +00:00
// On slot2 we allow reflector control IDs, but not secondary TG IDs unless specifically listed. Also allow echo.
2016-07-10 20:37:11 +00:00
if ( gt4k ) {
if ( std : : find ( m_dstWhiteListSlot2NET . begin ( ) , m_dstWhiteListSlot2NET . end ( ) , did ) ! = m_dstWhiteListSlot2NET . end ( ) | | did = = 0 )
2016-07-11 16:41:53 +00:00
return true ;
// If dstId in secondary TG range or whitelist
2016-07-10 20:37:11 +00:00
else if ( did > = 4000 ) {
if ( did > 5000U & & did < 10000U )
return false ;
else
return true ;
}
2016-07-11 16:41:53 +00:00
} else {
2016-07-10 20:37:11 +00:00
if ( std : : find ( m_dstWhiteListSlot2NET . begin ( ) , m_dstWhiteListSlot2NET . end ( ) , did ) ! = m_dstWhiteListSlot2NET . end ( ) )
return true ;
}
}
return false ;
2016-07-10 10:47:23 +00:00
} else {
2016-07-10 20:37:11 +00:00
if ( slot = = 1U ) {
if ( m_dstWhiteListSlot1RF . size ( ) = = 0U )
return true ;
2016-07-10 10:47:23 +00:00
2016-07-10 20:37:11 +00:00
// No reflectors on slot1, so we only allow all IDs over 99999 unless specifically whitelisted.
2016-07-11 16:41:53 +00:00
// Allow traffic to TG0 as I think this is a special case - need to confirm
2016-07-10 20:37:11 +00:00
if ( gt4k ) {
if ( std : : find ( m_dstWhiteListSlot1RF . begin ( ) , m_dstWhiteListSlot1RF . end ( ) , did ) ! = m_dstWhiteListSlot1RF . end ( ) | | did > = 99999U | | did = = 0 )
return true ;
} else {
if ( std : : find ( m_dstWhiteListSlot1RF . begin ( ) , m_dstWhiteListSlot1RF . end ( ) , did ) ! = m_dstWhiteListSlot1RF . end ( ) | | did = = 0 )
return true ;
}
} else {
if ( m_dstWhiteListSlot2RF . size ( ) = = 0U )
2016-07-10 10:47:23 +00:00
return true ;
2016-07-10 20:37:11 +00:00
2016-07-11 16:41:53 +00:00
// On slot2 we allow reflector control IDs, but not secondary TG IDs unless specifically listed. Also allow echo.
2016-07-10 20:37:11 +00:00
if ( gt4k ) {
2016-07-11 16:41:53 +00:00
if ( std : : find ( m_dstWhiteListSlot2RF . begin ( ) , m_dstWhiteListSlot2RF . end ( ) , did ) ! = m_dstWhiteListSlot2RF . end ( ) | | did = = 0 )
return true ;
// If dstId in secondary TG range or whitelist
2016-10-13 16:46:02 +00:00
else if ( did > = 4000U ) {
2016-07-10 20:37:11 +00:00
if ( did > 5000U & & did < 10000U )
return false ;
else
return true ;
}
2016-07-11 16:41:53 +00:00
} else {
2016-07-10 20:37:11 +00:00
if ( std : : find ( m_dstWhiteListSlot2RF . begin ( ) , m_dstWhiteListSlot2RF . end ( ) , did ) ! = m_dstWhiteListSlot2RF . end ( ) )
return true ;
}
}
2016-07-11 16:41:53 +00:00
return false ;
2016-07-10 10:47:23 +00:00
}
}
2016-07-10 15:46:02 +00:00
2016-11-10 18:43:54 +00:00
bool CDMRAccessControl : : validateSrcId ( unsigned int id )
2016-07-10 15:46:02 +00:00
{
if ( m_selfOnly ) {
return id = = m_id ;
} else {
2016-10-13 16:46:02 +00:00
if ( std : : find ( m_srcIdBlacklist . begin ( ) , m_srcIdBlacklist . end ( ) , id ) ! = m_srcIdBlacklist . end ( ) )
2016-07-10 15:46:02 +00:00
return false ;
unsigned int prefix = id / 10000U ;
if ( prefix = = 0U | | prefix > 999U )
return false ;
if ( m_prefixes . size ( ) = = 0U )
return true ;
return std : : find ( m_prefixes . begin ( ) , m_prefixes . end ( ) , prefix ) ! = m_prefixes . end ( ) ;
}
}
2016-07-10 16:32:00 +00:00
2016-11-10 18:43:54 +00:00
bool CDMRAccessControl : : validateAccess ( unsigned int src_id , unsigned int dst_id , unsigned int slot , bool network )
2016-07-10 16:32:00 +00:00
{
2016-07-10 16:48:09 +00:00
// source ID validation is only applied to RF traffic
2016-11-10 18:43:54 +00:00
if ( ! network & & ! CDMRAccessControl : : validateSrcId ( src_id ) ) {
2016-07-11 16:41:53 +00:00
LogMessage ( " DMR Slot %u, invalid access attempt from %u (blacklisted) " , slot , src_id ) ;
return false ;
2016-11-10 18:43:54 +00:00
} else if ( CDMRAccessControl : : dstIdBlacklist ( dst_id , slot , network ) ) {
2016-07-11 16:41:53 +00:00
LogMessage ( " DMR Slot %u, invalid access attempt to TG%u (TG blacklisted) " , slot , dst_id ) ;
return false ;
2016-11-10 18:43:54 +00:00
} else if ( ! CDMRAccessControl : : dstIdWhitelist ( dst_id , slot , true , network ) ) {
2016-07-11 16:41:53 +00:00
LogMessage ( " DMR Slot %u, invalid access attempt to TG%u (TG not in whitelist) " , slot , dst_id ) ;
return false ;
} else {
return true ;
}
2016-07-10 16:32:00 +00:00
}
2016-09-11 11:15:03 +00:00
2016-11-10 18:43:54 +00:00
unsigned int CDMRAccessControl : : dstIdRewrite ( unsigned int did , unsigned int sid , unsigned int slot , bool network , CDMRLC * dmrLC )
2016-09-11 11:15:03 +00:00
{
2016-10-13 16:46:02 +00:00
if ( slot = = 1U & & ! m_tgRewriteSlot1 )
return 0U ;
2016-09-15 19:41:14 +00:00
2016-10-13 16:46:02 +00:00
if ( slot = = 2U & & ! m_tgRewriteSlot2 )
return 0U ;
time_t currenttime = : : time ( NULL ) ;
2016-09-11 11:15:03 +00:00
2016-10-13 16:46:02 +00:00
if ( network ) {
2016-10-17 12:59:52 +00:00
2016-10-17 20:25:22 +00:00
m_dstRewriteID [ slot - 1U ] = did ;
m_srcID [ slot - 1U ] = sid ;
2016-10-13 16:46:02 +00:00
//not needed at present - for direct dial, which requires change at master end.
//memcpy(&m_lastdmrLC, &dmrLC, sizeof(dmrLC));
if ( m_bmAutoRewrite & & ( did < 4000U | | did > 5000U ) & & did > 0U & & did ! = 9U & & dmrLC - > getFLCO ( ) = = FLCO_GROUP ) {
LogMessage ( " DMR Slot %u, Rewrite DST ID (TG) of of inbound network traffic from %u to 9 " , slot , did ) ;
return 9U ;
// rewrite incoming BM voice prompts to TG 9
} else if ( m_bmRewriteReflectorVoicePrompts & & ( sid > = 4000U & & sid < = 5000U ) & & dmrLC - > getFLCO ( ) = = FLCO_USER_USER ) {
dmrLC - > setFLCO ( FLCO_GROUP ) ;
LogMessage ( " DMR Slot %u, Rewrite inbound private call to %u to Group Call on TG 9 (BM reflector voice prompt) " , slot , did ) ;
return 9U ;
} else {
return 0U ;
}
2016-10-17 20:25:22 +00:00
} else if ( m_bmAutoRewrite & & did = = 9U & & m_dstRewriteID [ slot - 1U ] ! = 9U & & m_dstRewriteID [ slot - 1U ] ! = 0U & & ( m_time [ slot - 1U ] + m_callHang ) > currenttime & & dmrLC - > getFLCO ( ) = = FLCO_GROUP ) {
LogMessage ( " DMR Slot %u, Rewrite DST ID (TG) of outbound network traffic from %u to %u (return traffic during CallHang) " , slot , did , m_dstRewriteID [ slot - 1 ] ) ;
return m_dstRewriteID [ slot - 1U ] ;
2016-11-10 18:46:13 +00:00
} else if ( m_bmAutoRewrite & & ( did < 4000U | | did > 5000U ) & & did > 0U & & did ! = 9U & & did ! = 9990U & & did < 99999U & & dmrLC - > getFLCO ( ) = = FLCO_USER_USER ) {
2016-10-17 20:25:22 +00:00
m_dstRewriteID [ slot - 1U ] = did ;
2016-10-13 16:46:02 +00:00
dmrLC - > setFLCO ( FLCO_GROUP ) ;
LogMessage ( " DMR Slot %u, Rewrite outbound private call to %u Group Call (Connect talkgroup by private call) " , slot , did ) ;
return did ;
2016-11-10 18:46:13 +00:00
} else if ( m_bmAutoRewrite & & ( did < 4000U | | did > 5000U ) & & did > 0U & & did ! = 9U & & did > 99999U ) {
2016-10-17 20:25:22 +00:00
m_dstRewriteID [ slot - 1U ] = did ;
2016-09-19 14:33:47 +00:00
}
2016-09-15 13:19:00 +00:00
2016-10-13 16:46:02 +00:00
return 0U ;
}
2016-09-16 12:51:24 +00:00
2016-11-10 18:43:54 +00:00
void CDMRAccessControl : : setOverEndTime ( unsigned int slot )
2016-09-15 13:19:00 +00:00
{
2016-10-17 20:25:22 +00:00
m_time [ slot - 1U ] = : : time ( NULL ) ;
2016-10-13 16:46:02 +00:00
}