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://yate.null.ro/svn/yate/trunk@4817 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
5505d3bca9
commit
c2487c52d8
|
@ -26,18 +26,44 @@
|
||||||
; Can be one of ITU,ANSI,ANSI8,China,Japan,Japan5
|
; Can be one of ITU,ANSI,ANSI8,China,Japan,Japan5
|
||||||
;pointcodetype=
|
;pointcodetype=
|
||||||
|
|
||||||
; defaultpointcode: string: DPC of the ISUP messages to intercept
|
; defaultpointcode: string: DPC of the ISUP messages to match
|
||||||
;defaultpointcode=
|
;defaultpointcode=
|
||||||
|
|
||||||
; remotepointcode: string: OPC of the ISUP messages to intercept
|
; remotepointcode: string: OPC of the ISUP messages to match
|
||||||
;remotepointcode=
|
;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 should be enabled if intercepting more than just IAM
|
||||||
;symmetric=no
|
;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
|
; intercept: keyword: What class of messages to intercept
|
||||||
|
; none: Intercept no message, just mangle routing label and CIC
|
||||||
; iam: Only intercept IAM
|
; iam: Only intercept IAM
|
||||||
; cdr: Intercept most CDR related messages: IAM,SAM,ACM,CPG,ANM,CON,SUS,RES,REL,RLC
|
; 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
|
; all: Intercept almost all messages, except UPT,UPA,NRM,PAM,CNF,USR
|
||||||
;intercept=iam
|
;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)
|
YCLASS(IsupIntercept,SS7ISUP)
|
||||||
public:
|
public:
|
||||||
enum What {
|
enum What {
|
||||||
Iam, // IAM only
|
None = 0, // No messages, just mangling
|
||||||
Cdr, // IAM,SAM,ACM,CPG,ANM,CON,SUS,RES,REL,RLC
|
Iam, // IAM only
|
||||||
|
Cdr, // IAM,SAM,ACM,CPG,ANM,CON,SUS,RES,REL,RLC
|
||||||
All
|
All
|
||||||
};
|
};
|
||||||
inline IsupIntercept(const NamedList& params)
|
inline IsupIntercept(const NamedList& params)
|
||||||
: SignallingComponent(params,¶ms), SS7ISUP(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);
|
virtual bool initialize(const NamedList* config);
|
||||||
void dispatched(SS7MsgISUP& isup, const Message& msg, const SS7Label& label, int sls, bool accepted);
|
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,
|
virtual bool processMSU(SS7MsgISUP::Type type, unsigned int cic,
|
||||||
const unsigned char* paramPtr, unsigned int paramLen,
|
const unsigned char* paramPtr, unsigned int paramLen,
|
||||||
const SS7Label& label, SS7Layer3* network, int sls);
|
const SS7Label& label, SS7Layer3* network, int sls);
|
||||||
|
bool shouldIntercept(SS7MsgISUP::Type type) const;
|
||||||
private:
|
private:
|
||||||
bool m_used;
|
bool m_used;
|
||||||
bool m_symmetric;
|
bool m_symmetric;
|
||||||
What m_what;
|
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
|
class IsupMessage : public Message
|
||||||
|
@ -89,6 +97,8 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
static const TokenDict s_dict_what[] = {
|
static const TokenDict s_dict_what[] = {
|
||||||
|
{ "nothing", IsupIntercept::None },
|
||||||
|
{ "none", IsupIntercept::None },
|
||||||
{ "IAM", IsupIntercept::Iam },
|
{ "IAM", IsupIntercept::Iam },
|
||||||
{ "iam", IsupIntercept::Iam },
|
{ "iam", IsupIntercept::Iam },
|
||||||
{ "CDR", IsupIntercept::Cdr },
|
{ "CDR", IsupIntercept::Cdr },
|
||||||
|
@ -98,6 +108,17 @@ static const TokenDict s_dict_what[] = {
|
||||||
{ 0, 0 }
|
{ 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;
|
static ObjList s_manglers;
|
||||||
|
|
||||||
INIT_PLUGIN(IsupMangler);
|
INIT_PLUGIN(IsupMangler);
|
||||||
|
@ -108,43 +129,29 @@ bool IsupIntercept::initialize(const NamedList* config)
|
||||||
if (!config)
|
if (!config)
|
||||||
return false;
|
return false;
|
||||||
SS7ISUP::initialize(config);
|
SS7ISUP::initialize(config);
|
||||||
|
SS7Router* router = YOBJECT(SS7Router,network());
|
||||||
|
m_resend = config->getBoolValue("resend",!(router && router->transferring()));
|
||||||
m_symmetric = config->getBoolValue("symmetric",m_symmetric);
|
m_symmetric = config->getBoolValue("symmetric",m_symmetric);
|
||||||
m_what = (What)config->getIntValue("intercept",s_dict_what,m_what);
|
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,"???"),
|
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;
|
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) {
|
switch (type) {
|
||||||
// always intercept IAM
|
// almost always intercept IAM
|
||||||
case SS7MsgISUP::IAM:
|
case SS7MsgISUP::IAM:
|
||||||
break;
|
return (m_what >= Iam);
|
||||||
// other CDR relevant messages
|
// other CDR relevant messages
|
||||||
case SS7MsgISUP::SAM:
|
case SS7MsgISUP::SAM:
|
||||||
case SS7MsgISUP::ACM:
|
case SS7MsgISUP::ACM:
|
||||||
|
@ -155,9 +162,7 @@ HandledMSU IsupIntercept::receivedMSU(const SS7MSU& msu, const SS7Label& label,
|
||||||
case SS7MsgISUP::RES:
|
case SS7MsgISUP::RES:
|
||||||
case SS7MsgISUP::REL:
|
case SS7MsgISUP::REL:
|
||||||
case SS7MsgISUP::RLC:
|
case SS7MsgISUP::RLC:
|
||||||
if (m_what >= Cdr)
|
return (m_what >= Cdr);
|
||||||
break;
|
|
||||||
return HandledMSU::Rejected;
|
|
||||||
// we shouldn't mess with these messages
|
// we shouldn't mess with these messages
|
||||||
case SS7MsgISUP::UPT:
|
case SS7MsgISUP::UPT:
|
||||||
case SS7MsgISUP::UPA:
|
case SS7MsgISUP::UPA:
|
||||||
|
@ -165,16 +170,83 @@ HandledMSU IsupIntercept::receivedMSU(const SS7MSU& msu, const SS7Label& label,
|
||||||
case SS7MsgISUP::PAM:
|
case SS7MsgISUP::PAM:
|
||||||
case SS7MsgISUP::CNF:
|
case SS7MsgISUP::CNF:
|
||||||
case SS7MsgISUP::USR:
|
case SS7MsgISUP::USR:
|
||||||
return HandledMSU::Rejected;
|
return false;
|
||||||
// intercepting all messages is risky
|
// intercepting all messages is risky
|
||||||
default:
|
default:
|
||||||
if (m_what >= All)
|
return (m_what >= All);
|
||||||
break;
|
}
|
||||||
// let the message pass through
|
}
|
||||||
|
|
||||||
|
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 HandledMSU::Rejected;
|
||||||
}
|
}
|
||||||
return processMSU(type,cic,s+3,len-3,label,network,sls) ?
|
// horrible - create a pair of writable aliases to alter data in place
|
||||||
HandledMSU::Accepted : HandledMSU::Rejected;
|
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,
|
bool IsupIntercept::processMSU(SS7MsgISUP::Type type, unsigned int cic,
|
||||||
|
|
Loading…
Reference in New Issue