Implemented matching by CIC range so multiple manglers can run on same PC.
Added capability to mangle routing label and CIC of ISUP messages. git-svn-id: http://voip.null.ro/svn/yate@4817 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
4013e12fd9
commit
2253665df5
|
@ -26,18 +26,44 @@
|
|||
; Can be one of ITU,ANSI,ANSI8,China,Japan,Japan5
|
||||
;pointcodetype=
|
||||
|
||||
; defaultpointcode: string: DPC of the ISUP messages to intercept
|
||||
; defaultpointcode: string: DPC of the ISUP messages to match
|
||||
;defaultpointcode=
|
||||
|
||||
; remotepointcode: string: OPC of the ISUP messages to intercept
|
||||
; remotepointcode: string: OPC of the ISUP messages to match
|
||||
;remotepointcode=
|
||||
|
||||
; symmetric: boolean: Intercept and mangle messages in the opposite direction too
|
||||
; symmetric: boolean: Match and mangle messages in the opposite direction too (DPC->OPC)
|
||||
; Symmetric should be enabled if intercepting more than just IAM
|
||||
;symmetric=no
|
||||
|
||||
; cic_min: int: Minimum circuit code to match
|
||||
;cic_min=1
|
||||
|
||||
; cic_max: int: Maximum circuit code to match
|
||||
;cic_max=16383
|
||||
|
||||
; intercept: keyword: What class of messages to intercept
|
||||
; none: Intercept no message, just mangle routing label and CIC
|
||||
; iam: Only intercept IAM
|
||||
; cdr: Intercept most CDR related messages: IAM,SAM,ACM,CPG,ANM,CON,SUS,RES,REL,RLC
|
||||
; all: Intercept almost all messages, except UPT,UPA,NRM,PAM,CNF,USR
|
||||
;intercept=iam
|
||||
|
||||
|
||||
; The following set: settings apply to all matched messages, not just those intercepted
|
||||
; These mangle the routing label and circuit codes before any other handling
|
||||
|
||||
; set:opc: int: OPC numeric value to overwrite in message label
|
||||
; The special value "mirror" will set the received DPC
|
||||
;set:opc=
|
||||
|
||||
; set:dpc: int: DPC numeric value to overwrite in message label
|
||||
; The special value "mirror" will set the received OPC
|
||||
;set:dpc=
|
||||
|
||||
; set:sls: int: Signaling Link Selection to overwrite in message label
|
||||
; The special value "cic" will use the circuit code after any altering
|
||||
;set:sls=
|
||||
|
||||
; set:cic: int: Offset to apply to the circuit codes in message body
|
||||
;set:cic=0
|
||||
|
|
|
@ -34,13 +34,17 @@ class IsupIntercept : public SS7ISUP
|
|||
YCLASS(IsupIntercept,SS7ISUP)
|
||||
public:
|
||||
enum What {
|
||||
None = 0, // No messages, just mangling
|
||||
Iam, // IAM only
|
||||
Cdr, // IAM,SAM,ACM,CPG,ANM,CON,SUS,RES,REL,RLC
|
||||
All
|
||||
};
|
||||
inline IsupIntercept(const NamedList& params)
|
||||
: SignallingComponent(params,¶ms), SS7ISUP(params),
|
||||
m_used(true), m_symmetric(false), m_what(Iam)
|
||||
m_used(true), m_symmetric(false), m_what(Iam),
|
||||
m_cicMin(1), m_cicMax(16383),
|
||||
m_setOpc(0), m_setDpc(0), m_setSls(-2), m_setCic(0),
|
||||
m_resend(true)
|
||||
{ }
|
||||
virtual bool initialize(const NamedList* config);
|
||||
void dispatched(SS7MsgISUP& isup, const Message& msg, const SS7Label& label, int sls, bool accepted);
|
||||
|
@ -50,10 +54,14 @@ protected:
|
|||
virtual bool processMSU(SS7MsgISUP::Type type, unsigned int cic,
|
||||
const unsigned char* paramPtr, unsigned int paramLen,
|
||||
const SS7Label& label, SS7Layer3* network, int sls);
|
||||
bool shouldIntercept(SS7MsgISUP::Type type) const;
|
||||
private:
|
||||
bool m_used;
|
||||
bool m_symmetric;
|
||||
What m_what;
|
||||
unsigned int m_cicMin, m_cicMax;
|
||||
int m_setOpc, m_setDpc, m_setSls, m_setCic;
|
||||
bool m_resend;
|
||||
};
|
||||
|
||||
class IsupMessage : public Message
|
||||
|
@ -89,6 +97,8 @@ public:
|
|||
};
|
||||
|
||||
static const TokenDict s_dict_what[] = {
|
||||
{ "nothing", IsupIntercept::None },
|
||||
{ "none", IsupIntercept::None },
|
||||
{ "IAM", IsupIntercept::Iam },
|
||||
{ "iam", IsupIntercept::Iam },
|
||||
{ "CDR", IsupIntercept::Cdr },
|
||||
|
@ -98,6 +108,17 @@ static const TokenDict s_dict_what[] = {
|
|||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static const TokenDict s_dict_pc[] = {
|
||||
{ "mirror", -1 },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static const TokenDict s_dict_sls[] = {
|
||||
{ "cic", -1 },
|
||||
{ "circuit", -1 },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static ObjList s_manglers;
|
||||
|
||||
INIT_PLUGIN(IsupMangler);
|
||||
|
@ -108,43 +129,29 @@ bool IsupIntercept::initialize(const NamedList* config)
|
|||
if (!config)
|
||||
return false;
|
||||
SS7ISUP::initialize(config);
|
||||
SS7Router* router = YOBJECT(SS7Router,network());
|
||||
m_resend = config->getBoolValue("resend",!(router && router->transferring()));
|
||||
m_symmetric = config->getBoolValue("symmetric",m_symmetric);
|
||||
m_what = (What)config->getIntValue("intercept",s_dict_what,m_what);
|
||||
Debug(this,DebugAll,"Added %u Point Codes, intercepts %s %s",
|
||||
m_cicMin = config->getIntValue("cic_min",m_cicMin);
|
||||
m_cicMax = config->getIntValue("cic_max",m_cicMax);
|
||||
m_setOpc = config->getIntValue("set:opc",s_dict_pc,m_setOpc);
|
||||
m_setDpc = config->getIntValue("set:dpc",s_dict_pc,m_setDpc);
|
||||
m_setSls = config->getIntValue("set:sls",s_dict_sls,m_setSls);
|
||||
m_setCic = config->getIntValue("set:cic",m_setCic);
|
||||
Debug(this,DebugAll,"Added %u Point Codes, intercepts %s %s, cic=%u-%u",
|
||||
setPointCode(*config),lookup(m_what,s_dict_what,"???"),
|
||||
(m_symmetric) ? "both ways" : "one way");
|
||||
(m_symmetric) ? "both ways" : "one way",
|
||||
m_cicMin,m_cicMax);
|
||||
return true;
|
||||
}
|
||||
|
||||
HandledMSU IsupIntercept::receivedMSU(const SS7MSU& msu, const SS7Label& label, SS7Layer3* network, int sls)
|
||||
bool IsupIntercept::shouldIntercept(SS7MsgISUP::Type type) const
|
||||
{
|
||||
if (msu.getSIF() != sif())
|
||||
return HandledMSU::Rejected;
|
||||
if (!hasPointCode(label.dpc()) || !handlesRemotePC(label.opc())) {
|
||||
if (!m_symmetric || !hasPointCode(label.opc()) || !handlesRemotePC(label.dpc()))
|
||||
return HandledMSU::Rejected;
|
||||
}
|
||||
// we should have at least 2 bytes CIC and 1 byte message type
|
||||
const unsigned char* s = msu.getData(label.length()+1,3);
|
||||
if (!s) {
|
||||
Debug(this,DebugNote,"Got short MSU");
|
||||
return HandledMSU::Rejected;
|
||||
}
|
||||
unsigned int len = msu.length()-label.length()-1;
|
||||
unsigned int cic = s[0] | (s[1] << 8);
|
||||
SS7MsgISUP::Type type = (SS7MsgISUP::Type)s[2];
|
||||
String name = SS7MsgISUP::lookup(type);
|
||||
if (!name) {
|
||||
String tmp;
|
||||
tmp.hexify((void*)s,len,' ');
|
||||
Debug(this,DebugMild,"Received unknown ISUP type 0x%02x, cic=%u, length %u: %s",
|
||||
type,cic,len,tmp.c_str());
|
||||
name = (int)type;
|
||||
}
|
||||
switch (type) {
|
||||
// always intercept IAM
|
||||
// almost always intercept IAM
|
||||
case SS7MsgISUP::IAM:
|
||||
break;
|
||||
return (m_what >= Iam);
|
||||
// other CDR relevant messages
|
||||
case SS7MsgISUP::SAM:
|
||||
case SS7MsgISUP::ACM:
|
||||
|
@ -155,9 +162,7 @@ HandledMSU IsupIntercept::receivedMSU(const SS7MSU& msu, const SS7Label& label,
|
|||
case SS7MsgISUP::RES:
|
||||
case SS7MsgISUP::REL:
|
||||
case SS7MsgISUP::RLC:
|
||||
if (m_what >= Cdr)
|
||||
break;
|
||||
return HandledMSU::Rejected;
|
||||
return (m_what >= Cdr);
|
||||
// we shouldn't mess with these messages
|
||||
case SS7MsgISUP::UPT:
|
||||
case SS7MsgISUP::UPA:
|
||||
|
@ -165,16 +170,83 @@ HandledMSU IsupIntercept::receivedMSU(const SS7MSU& msu, const SS7Label& label,
|
|||
case SS7MsgISUP::PAM:
|
||||
case SS7MsgISUP::CNF:
|
||||
case SS7MsgISUP::USR:
|
||||
return HandledMSU::Rejected;
|
||||
return false;
|
||||
// intercepting all messages is risky
|
||||
default:
|
||||
if (m_what >= All)
|
||||
break;
|
||||
// let the message pass through
|
||||
return (m_what >= All);
|
||||
}
|
||||
}
|
||||
|
||||
HandledMSU IsupIntercept::receivedMSU(const SS7MSU& msu, const SS7Label& label, SS7Layer3* network, int sls)
|
||||
{
|
||||
if (msu.getSIF() != sif())
|
||||
return HandledMSU::Rejected;
|
||||
if (!hasPointCode(label.dpc()) || !handlesRemotePC(label.opc())) {
|
||||
if (!m_symmetric || !hasPointCode(label.opc()) || !handlesRemotePC(label.dpc()))
|
||||
return HandledMSU::Rejected;
|
||||
}
|
||||
return processMSU(type,cic,s+3,len-3,label,network,sls) ?
|
||||
HandledMSU::Accepted : HandledMSU::Rejected;
|
||||
// horrible - create a pair of writable aliases to alter data in place
|
||||
SS7MSU& rwMsu = const_cast<SS7MSU&>(msu);
|
||||
SS7Label& rwLbl = const_cast<SS7Label&>(label);
|
||||
// we should have at least 2 bytes CIC and 1 byte message type
|
||||
unsigned char* s = rwMsu.getData(label.length()+1,3);
|
||||
if (!s) {
|
||||
Debug(this,DebugNote,"Got short MSU");
|
||||
return HandledMSU::Rejected;
|
||||
}
|
||||
unsigned int len = msu.length()-label.length()-1;
|
||||
unsigned int cic = s[0] | (s[1] << 8);
|
||||
if (cic < m_cicMin || cic > m_cicMax)
|
||||
return HandledMSU::Rejected;
|
||||
|
||||
SS7MsgISUP::Type type = (SS7MsgISUP::Type)s[2];
|
||||
String name = SS7MsgISUP::lookup(type);
|
||||
if (!name) {
|
||||
String tmp;
|
||||
tmp.hexify((void*)s,len,' ');
|
||||
Debug(this,DebugMild,"Received unknown ISUP type 0x%02x, cic=%u, length %u: %s",
|
||||
type,cic,len,tmp.c_str());
|
||||
name = (int)type;
|
||||
}
|
||||
XDebug(this,DebugAll,"Received ISUP type %s, cic=%u, length %u",name.c_str(),cic,len);
|
||||
|
||||
// intercepted as message or not, apply mangling now
|
||||
if (m_setCic) {
|
||||
cic += m_setCic;
|
||||
s[0] = (cic & 0xff);
|
||||
s[1] = ((cic >> 8) & 0xff);
|
||||
}
|
||||
bool changed = false;
|
||||
if (m_setSls >= -1) {
|
||||
changed = true;
|
||||
rwLbl.setSls(((m_setSls >= 0) ? m_setSls : cic) & 0xff);
|
||||
}
|
||||
if (m_setOpc || m_setDpc) {
|
||||
changed = true;
|
||||
SS7PointCode opc(label.opc());
|
||||
SS7PointCode dpc(label.dpc());
|
||||
if (m_setOpc > 0)
|
||||
rwLbl.opc().unpack(label.type(),m_setOpc);
|
||||
else if (m_setOpc < 0)
|
||||
rwLbl.opc() = dpc;
|
||||
if (m_setDpc > 0)
|
||||
rwLbl.dpc().unpack(label.type(),m_setDpc);
|
||||
else if (m_setDpc < 0)
|
||||
rwLbl.dpc() = opc;
|
||||
}
|
||||
if (changed)
|
||||
rwLbl.store(rwMsu.getData(1));
|
||||
|
||||
if (shouldIntercept(type) && processMSU(type,cic,s+3,len-3,label,network,sls))
|
||||
return HandledMSU::Accepted;
|
||||
if (!(m_setDpc || m_resend))
|
||||
return HandledMSU::Rejected;
|
||||
// if we altered the DPC or we are no STP we should transmit as new message
|
||||
if (transmitMSU(rwMsu,rwLbl,rwLbl.sls()) >= 0)
|
||||
return HandledMSU::Accepted;
|
||||
Debug(this,DebugWarn,"Failed to forward mangled %s (%u) [%p]",
|
||||
SS7MsgISUP::lookup(type),cic,this);
|
||||
return HandledMSU::Failure;
|
||||
}
|
||||
|
||||
bool IsupIntercept::processMSU(SS7MsgISUP::Type type, unsigned int cic,
|
||||
|
|
Loading…
Reference in New Issue