1008 lines
32 KiB
C
1008 lines
32 KiB
C
|
|
/***************************************************************/
|
|
/*Title: scrc.c */
|
|
/*Descr: SCCP Routing Control Procedure */
|
|
/*Author: Liang Hanxi */
|
|
/*Create: 2002-2-19 */
|
|
/*Modify: 2003-5-9 */
|
|
|
|
/***************************************************************/
|
|
#include "./include/sccp.h"
|
|
#include "./include/sccp_pub.h"
|
|
#include "../../public/src/include/pub_netcap.h"
|
|
|
|
extern int sccp_send_netcap ;
|
|
|
|
/*===========export================*/
|
|
void scrc_timer ( );
|
|
int scrc_route ( Intra_Msg * pIntraMsg, BOOL ForceAnsi );
|
|
int scrc_mnp_route ( Intra_Msg * pIntraMsg, BOOL ForceAnsi );
|
|
int send_msg ( Intra_Msg * pIntraMsg, BYTE ansi_flag );
|
|
int scrc_rf ( Intra_Msg * pIntraMsg, BYTE AnsiFlag );
|
|
DWORD SelectIPOfSSN ( BYTE ssn, BYTE sls, BOOL from_mtp );
|
|
|
|
/*===========import================*/
|
|
extern int SegmentingMsg ( Intra_Msg * pIntraMsg ); //sclc.c
|
|
extern int build_msg ( BYTE * buf, Intra_Msg * intramsg, BYTE NetID, BYTE ansi_flag );
|
|
extern int parse_msg ( BYTE * buf, Intra_Msg * intramsg, int len, BYTE NetID, BYTE ansi_flag ); //sccpmsg.c
|
|
extern int scrc2scoc ( Intra_Msg * intramsg, BYTE AnsiFlag );
|
|
extern int scoc_store ( up_message * sccpmsg );
|
|
extern int Digits2Array ( BYTE * pArray, BYTE * pDigits, int DigitsLen );
|
|
extern u_short SelectRoute ( BYTE * pDigits, BYTE DigitsLen );
|
|
extern void TranslateGT ( SCCP_ADDR * addr, SCCP_ROUTE * pRoute );
|
|
extern int sclc2scmg ( Intra_Msg * intramsg );
|
|
extern BOOL CheckAvail ( SCCP_ADDR * addr );
|
|
extern int scrc2sclc ( Intra_Msg * pIntraMsg );
|
|
extern int sclc_rf ( Intra_Msg * pIntraMsg );
|
|
extern BOOL isco ( Intra_Msg * intramsg );
|
|
extern void snmpLogInfo ( char *logInfo );
|
|
|
|
/* by simon at 23/9/26 */
|
|
extern SCCP_CSTA SccpCsta[96];
|
|
extern DWORD SccpCstaInd;
|
|
extern LOCAL_SSN LocalSSN[256];
|
|
extern SCCP_SegMsgBuf sccp_segmsgbuf[MAX_SEGMSG_BUF];
|
|
extern struct sccp_msg_statistic
|
|
{
|
|
DWORD msg_mtp_scoc;
|
|
DWORD msg_scoc_up;
|
|
DWORD mnp_send;
|
|
DWORD mnp_route;
|
|
} sccpmsg_st;
|
|
extern struct _dpc2sls
|
|
{
|
|
int dpc;
|
|
u8 sls;
|
|
} dpc2sls[256]; // used for sequence control, add by Roy Jiang, 2007-09-17
|
|
extern SCCP_Capture_Buf SCCPCapBuf;
|
|
extern LOCAL_SSN LocalSSN[256];
|
|
extern int RelatedSSNNum;
|
|
extern RL_SSN RelatedSSN[SCCP_RLSSN_NUM];
|
|
extern SCOC_BUF ScocBuf;
|
|
extern SCCP_ROUTE RouteList[SCCP_ROUTE_NUM];
|
|
extern SCCP_OPT SCCP_Param;
|
|
extern u8 MNP_Flag[2];
|
|
|
|
/*===========private================*/
|
|
static int mtp2scrc ( up_message * pMsgFromMTP );
|
|
void sccp_put_capture_logs ( BYTE person, BYTE * pictures, int len );
|
|
int get_sls(int dpc);
|
|
/******************************************************************/
|
|
|
|
/*==================Interface function----->================*/
|
|
|
|
/******************************************************************/
|
|
void scrc_timer ( ) //called per 20ms
|
|
//read messge from mtp buffer
|
|
{
|
|
up_message MsgFromMTP3;
|
|
BYTE loop = 128;
|
|
|
|
while ( loop-- > 0 )
|
|
{
|
|
if( sccp_GetMsg ( &MsgFromMTP3 ) > 0 )
|
|
mtp2scrc ( &MsgFromMTP3 );
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
|
|
u32 dAlterIpBackup; //for protection
|
|
int mtp2scrc ( up_message * pMsgFromMTP )
|
|
{
|
|
Intra_Msg msgin;
|
|
BOOL ForceAnsi = 0;
|
|
int mask;
|
|
char *pStr;
|
|
|
|
SccpCsta[SccpCstaInd].utilization[0]++;
|
|
|
|
memset ( &msgin, 0, sizeof ( Intra_Msg ) );
|
|
msgin.NetID = msgin.CGA.NetID = msgin.CDA.NetID = pMsgFromMTP->sio >> 6;
|
|
msgin.DPC = pMsgFromMTP->dpc;
|
|
msgin.OPC = pMsgFromMTP->opc;
|
|
msgin.SLS = pMsgFromMTP->cic[0] & 0x0F;
|
|
msgin.link = pMsgFromMTP->link;
|
|
|
|
ForceAnsi = ( pMsgFromMTP->sio >> 4 ) & 1;
|
|
parse_msg ( pMsgFromMTP->msgList, &msgin, pMsgFromMTP->len, msgin.NetID, ForceAnsi );
|
|
|
|
if( msgin.CDA.len > ( MAX_DIGITS * 2 ) )
|
|
{
|
|
SCCPCapBuf.watch_dog[14]++;
|
|
sccp_put_capture_logs ( 03, ( BYTE * ) pMsgFromMTP, sizeof ( up_message ) );
|
|
spLogDebug ( SCCPDB_ERR, "SCCP RV Invalid Message from MTP3,CDA.len=%d, len is over range, the Message was captured", msgin.CDA.len );
|
|
}
|
|
|
|
msgin.msgsource = FROM_MTP;
|
|
|
|
if( msgin.CGA.DPC == SCCP_Param.spc[msgin.NetID] )
|
|
msgin.CGA.ip = pMsgFromMTP->dest_ip;
|
|
else
|
|
msgin.CGA.ip = INADDR_NONE;
|
|
msgin.CDA.ip = INADDR_NONE;
|
|
|
|
switch ( msgin.msgtype )
|
|
{
|
|
case UDT_MSG:
|
|
SccpCsta[SccpCstaInd].quality[2]++;
|
|
spShowMsg ( SCCPDB_MTP3, "SCCP <== MTP3. UDT Message", &msgin );
|
|
return scrc_route ( &msgin, ForceAnsi );
|
|
case UDTS_MSG:
|
|
SccpCsta[SccpCstaInd].quality[3]++;
|
|
spShowMsg ( SCCPDB_MTP3, "SCCP <== MTP3. UDTS Message", &msgin );
|
|
return scrc_route ( &msgin, ForceAnsi );
|
|
case XUDT_MSG:
|
|
//SccpCsta[SccpCstaInd].quality[3]++;
|
|
mask = 0;
|
|
if( msgin.SegPresent == 1 )
|
|
{
|
|
mask |= SCCPDB_XUDT;
|
|
}
|
|
|
|
spShowMsg ( SCCPDB_MTP3 | mask, "SCCP_RegProc <== SCCP <== MTP3. XUDT Message", &msgin );
|
|
return scrc_route ( &msgin, ForceAnsi );
|
|
case XUDTS_MSG:
|
|
//SccpCsta[SccpCstaInd].quality[3]++;
|
|
spShowMsg ( SCCPDB_MTP3, "SCCP <== MTP3. XUDTS Message", &msgin );
|
|
return scrc_route ( &msgin, ForceAnsi );
|
|
case CR_MSG:
|
|
SccpCsta[SccpCstaInd].quality[6]++;
|
|
spShowMsg ( SCCPDB_AIF, "SCCP <== MTP3. CR Message", &msgin );
|
|
return scrc_route ( &msgin, ForceAnsi );
|
|
case DT1_MSG:
|
|
case CC_MSG:
|
|
case DT2_MSG:
|
|
case RLSD_MSG:
|
|
case RLC_MSG:
|
|
case CREF_MSG:
|
|
case AK_MSG:
|
|
case IT_MSG:
|
|
//message redirect, add by Roy Jiang
|
|
if (msgin.aDLR[0] != pSp->dSysID //not local system
|
|
&& msgin.aDLR[0] <= 2 && msgin.aDLR[0] != 0) //only system 1 & system 2
|
|
{
|
|
//dual server mode and the message is to the other server
|
|
if(pSp->dAlterIP == 0)
|
|
{
|
|
if (dAlterIpBackup != 0){
|
|
spLogDebug ( SCCPDB_ERR, "Fatal error, memory corrupted, pSp->dAlterIp = 0.");
|
|
pSp->dAlterIP = dAlterIpBackup;
|
|
}
|
|
else
|
|
return 0;
|
|
}
|
|
msgin.CDA.ip = pSp->dAlterIP;
|
|
msgin.msgsource = FROM_MTP;
|
|
msgin.redirectFlag = 1;
|
|
//send_msg ( &msgin, 0 ); //uAnsiFlag = 0;
|
|
pMsgFromMTP->dest_ip = pSp->dAlterIP;
|
|
pMsgFromMTP->link = 0xff;
|
|
sccp_redirect(pMsgFromMTP);
|
|
spGetMsgStr ( msgin.msgtype, pStr );
|
|
spShowMsg(SCCPDB_MTP3, "Message redirected. SCCP ==> MTP3.", &msgin);
|
|
// spLogDebug ( SCCPDB_AIF, "Message redirected. CO-%s, NetID=%d, msglen=%d", pStr, msgin.NetID, msgin.msglen );
|
|
return 0;
|
|
}
|
|
if( msgin.msgtype == DT1_MSG )
|
|
SccpCsta[SccpCstaInd].utilization[9 - 3]++;
|
|
else if( msgin.msgtype == DT1_MSG )
|
|
SccpCsta[SccpCstaInd].utilization[11 - 3]++;
|
|
|
|
spGetMsgStr ( msgin.msgtype, pStr );
|
|
spLogDebug ( SCCPDB_AIF, "SCCP <== MTP3. CO-%s, NetID=%d, msglen=%d ", pStr, msgin.NetID, msgin.msglen );
|
|
|
|
{
|
|
char digits1[24], digits2[24]; //, info[256];
|
|
|
|
BcdToAscii ( digits1, msgin.aSLR, 6 );
|
|
digits1[6] = 0;
|
|
BcdToAscii ( digits2, msgin.aDLR, 6 );
|
|
digits2[6] = 0;
|
|
spLogDebug ( SCCPDB_AIF,"SLR = %s DLR = %s ", digits1, digits2 );
|
|
}
|
|
spShowBCD ( SCCPDB_AIF, ( BYTE * ) pMsgFromMTP, ( pMsgFromMTP->len + 17 ) % 256 );
|
|
|
|
#ifndef _WXC_TEST
|
|
/*
|
|
if( SCCP_Param.CO_SSN <= 1 )
|
|
return scrc_rf ( &msgin, ForceAnsi );
|
|
|
|
msgin.CDA.ip = SelectIPOfSSN ( SCCP_Param.CO_SSN, msgin.SLS, 1 );
|
|
|
|
if( msgin.CDA.ip == SCCP_Param.ip )
|
|
{
|
|
return scoc_store ( pMsgFromMTP );
|
|
}
|
|
else if( msgin.CDA.ip == 0 )
|
|
return scrc_rf ( &msgin, ForceAnsi );
|
|
else
|
|
return send_msg ( &msgin, ForceAnsi );
|
|
*/
|
|
#endif
|
|
//need to modify
|
|
cr2co ( &msgin, ForceAnsi );
|
|
return 1;
|
|
//break;
|
|
default:
|
|
spLogDebug ( SCCPDB_ERR, "SCCP <== MTP3. Not support Message(type=%02x), NetID=%d, msglen=%d", msgin.msgtype, msgin.NetID, msgin.msglen );
|
|
spShowBCD ( SCCPDB_ERR, ( BYTE * ) pMsgFromMTP, ( pMsgFromMTP->len + 17 ) % 256 );
|
|
SCCPCapBuf.watch_dog[12]++; //invalid message
|
|
SCCPCapBuf.watch_dog[13] = msgin.msgtype; //invalid message
|
|
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/******************************************************************/
|
|
|
|
/*========== Routing Control Procedure-----> ===========*/
|
|
|
|
/******************************************************************/
|
|
int scrc_route ( Intra_Msg * pIntraMsg, BOOL ForceAnsi )
|
|
{
|
|
SCCP_ADDR *pAddr = NULL, DstAddr;
|
|
SCCP_ROUTE *pRoute = NULL;
|
|
int LocalSPC;
|
|
u_short nRoute = 0xFFFF;
|
|
BYTE Num[32], NumLen;
|
|
BYTE routeAI;
|
|
BYTE field = 0;
|
|
|
|
SccpCsta[SccpCstaInd].utilization[0]++;
|
|
pIntraMsg->msgMNP = 0;
|
|
|
|
pAddr = &pIntraMsg->CDA;
|
|
/* daniel */
|
|
pAddr->AI = 1; //default to include DPC
|
|
pIntraMsg->CGA.AI = 1; //default to include DPC
|
|
/* daniel */
|
|
memcpy ( &DstAddr, pAddr, sizeof ( SCCP_ADDR ) );
|
|
|
|
if( pAddr->RI == RI_SSN && pAddr->DPC == 0 )
|
|
{
|
|
if( pAddr->NetID > 3 )
|
|
{
|
|
spLogDebug ( SCCPDB_ERR, "<011>SCCP Translation:SPC not available" );
|
|
SccpCsta[SccpCstaInd].error[0]++;
|
|
return -1;
|
|
}
|
|
DstAddr.DPC = SCCP_Param.spc[pAddr->NetID];
|
|
}
|
|
//Route On GT
|
|
if( DstAddr.RI == RI_GT || DstAddr.DPC == 0 || DstAddr.SSN == 0 || DstAddr.NetID > 3 )
|
|
{
|
|
SccpCsta[SccpCstaInd].utilization[5 - 3]++;
|
|
if( pIntraMsg->CDA.GTI == 0 )
|
|
{
|
|
pIntraMsg->cause = RT_NTFN;
|
|
spLogDebug ( SCCPDB_ERR, "<011>SCCP Translation:GTI == 0 (4 is recommended)" );
|
|
SccpCsta[SccpCstaInd].error[1]++;
|
|
return -1;
|
|
}
|
|
/* if(pIntraMsg->CDA.TT != 0)
|
|
{
|
|
spLogDebug(SCCPDB_ERR, "<012>SCCP Translation:no translation for an address of such nature(TT=%d)", pIntraMsg->CDA.TT);
|
|
pIntraMsg->cause = RT_NTFN;
|
|
SccpCsta[SccpCstaInd].error[0] ++;
|
|
return -1;
|
|
} */
|
|
|
|
if( pAddr->len > ( MAX_DIGITS * 2 ) )
|
|
{
|
|
SCCPCapBuf.watch_dog[0]++;
|
|
sccp_put_capture_logs ( 01, ( BYTE * ) pIntraMsg, sizeof ( Intra_Msg ) );
|
|
spLogDebug ( SCCPDB_ERR, "<014>SCCP Receive Invalid Message,GTT len=%d, the Message was discarded and captured", pAddr->len );
|
|
return -2;
|
|
}
|
|
|
|
if( pAddr->NP > 0 )
|
|
Num[field++] = pAddr->NP;
|
|
else
|
|
Num[field++] = NP_MSISDN;
|
|
if( pAddr->TT > 0 )
|
|
{
|
|
Num[field++] = pAddr->TT / 100;
|
|
Num[field++] = ( pAddr->TT / 10 ) % 10;
|
|
Num[field++] = pAddr->TT % 10;
|
|
}
|
|
else
|
|
{
|
|
Num[field++] = TT_0;
|
|
Num[field++] = TT_1;
|
|
Num[field++] = TT_4;
|
|
}
|
|
NumLen = pAddr->len % ( MAX_DIGITS * 2 );
|
|
Digits2Array ( Num + field, pAddr->GTAI, ( NumLen + 1 ) / 2 );
|
|
nRoute = SelectRoute ( Num, NumLen + field );
|
|
|
|
if( nRoute < SCCP_ROUTE_NUM )
|
|
{
|
|
pRoute = &RouteList[nRoute];
|
|
|
|
if( DstAddr.NetID != pRoute->NetID )
|
|
pIntraMsg->CGA.RI = RI_GT;
|
|
/* daniel */
|
|
else if( pIntraMsg->msgsource != FROM_MTP )
|
|
pIntraMsg->CGA.RI = pRoute->RI;
|
|
/* daniel */
|
|
DstAddr.NetID = pRoute->NetID;
|
|
|
|
if( pRoute->SSN > 0 )
|
|
pAddr->SSN = DstAddr.SSN = pRoute->SSN;
|
|
|
|
pAddr->RI = pRoute->RI;
|
|
DstAddr.DPC = pRoute->DPC[0] * 0x10000 + pRoute->DPC[1] * 0x100 + pRoute->DPC[2];
|
|
|
|
if(( pIntraMsg->CGA.SSN != 10 ) && ( DstAddr.SSN == 6 && DstAddr.NP == 1 && pIntraMsg->data[0] == 0x62 ) && (MNP_Flag[0] != 0))
|
|
{// MNP neednot convert GT
|
|
if(!((pRoute->ReplaceStart == 1) && (pRoute->ReplaceEnd == pAddr->len)))
|
|
{
|
|
if( pRoute->convert )
|
|
{
|
|
DstAddr.RI = pAddr->RI;
|
|
TranslateGT ( &DstAddr, pRoute );
|
|
memcpy ( pAddr, &DstAddr, sizeof ( SCCP_ADDR ) );
|
|
}
|
|
}
|
|
}
|
|
else if( pRoute->convert )
|
|
{
|
|
DstAddr.RI = pAddr->RI;
|
|
TranslateGT ( &DstAddr, pRoute );
|
|
memcpy ( pAddr, &DstAddr, sizeof ( SCCP_ADDR ) );
|
|
}
|
|
|
|
/* daniel */
|
|
routeAI = pRoute->AI;
|
|
//set calling address
|
|
if( pIntraMsg->CGA.RI == 0 ) //route on GT
|
|
{
|
|
if( ( routeAI & 1 ) == 0 ) //point code no need
|
|
pIntraMsg->CGA.AI &= ~1; //set dpc=0
|
|
}
|
|
else //route on DPC+SSN
|
|
{
|
|
if( ( routeAI & 4 ) == 0 ) //GT no need
|
|
pIntraMsg->CGA.GTI = 0; //set GT=0
|
|
}
|
|
|
|
//set called address
|
|
if( pAddr->RI == 0 ) //route on GT
|
|
{
|
|
if( ( routeAI & 1 ) == 0 ) //point code no need
|
|
pAddr->AI &= ~1; //set dpc=0
|
|
}
|
|
else //route on DPC+SSN
|
|
{
|
|
if( ( routeAI & 4 ) == 0 ) //GT no need
|
|
pAddr->GTI = 0; //set GTI=0
|
|
}
|
|
/* daniel */
|
|
|
|
}
|
|
else if( nRoute >= 1024 && nRoute < 1024 + 256 ) //local Node
|
|
{
|
|
pAddr->SSN = DstAddr.SSN = nRoute - 1024;
|
|
if( DstAddr.NetID > 3 )
|
|
DstAddr.NetID = LocalSSN[DstAddr.SSN].NetID;
|
|
|
|
pAddr->RI = RI_SSN;
|
|
DstAddr.DPC = SCCP_Param.spc[DstAddr.NetID & 3];
|
|
}
|
|
else
|
|
{
|
|
pIntraMsg->cause = RT_NTFA;
|
|
SccpCsta[SccpCstaInd].avail[1]++;
|
|
if( ForceAnsi )
|
|
return scrc_rf ( pIntraMsg, 1 );
|
|
else
|
|
return scrc_rf ( pIntraMsg, mtp3_ansiFlag ( DstAddr.NetID ) );
|
|
}
|
|
}
|
|
if( !CheckAvail ( &DstAddr ) )
|
|
{
|
|
pIntraMsg->cause = RT_SF;
|
|
if( ForceAnsi )
|
|
return scrc_rf ( pIntraMsg, 1 );
|
|
else
|
|
return scrc_rf ( pIntraMsg, mtp3_ansiFlag ( DstAddr.NetID ) );
|
|
}
|
|
|
|
pIntraMsg->NetID = DstAddr.NetID % 4; //0~3
|
|
pIntraMsg->DPC = pAddr->DPC = DstAddr.DPC;
|
|
LocalSPC = SCCP_Param.spc[pIntraMsg->NetID];
|
|
|
|
if (pIntraMsg->CGA.RI == RI_SSN)
|
|
{
|
|
if (pIntraMsg->CGA.DPC == 0)
|
|
{
|
|
pIntraMsg->CGA.DPC = pIntraMsg->OPC;
|
|
}
|
|
}
|
|
|
|
if (pIntraMsg->CGA.RI == RI_SSN)
|
|
{
|
|
if (pIntraMsg->CGA.DPC == 0)
|
|
{
|
|
pIntraMsg->CGA.DPC = pIntraMsg->OPC;
|
|
}
|
|
}
|
|
|
|
if( DstAddr.DPC != LocalSPC )
|
|
{
|
|
snmpLogInfo ( "scrc_route(): start.... 266" );
|
|
|
|
if (pIntraMsg->sequenceFlag == 1 && pIntraMsg->msgtype == UDT_MSG){
|
|
pIntraMsg->SLS = get_sls(pIntraMsg->DPC); //in-sequence delivery, add by Roy Jiang, 07-09-26
|
|
pIntraMsg->msgclass = 1;
|
|
}
|
|
if( ForceAnsi )
|
|
return send_msg ( pIntraMsg, 1 );
|
|
else
|
|
return send_msg ( pIntraMsg, mtp3_ansiFlag ( DstAddr.NetID ) );
|
|
}
|
|
else if( pIntraMsg->msgtype == UDTS_MSG && pIntraMsg->msgsource == FROM_MTP) //discast UDTS message to local node
|
|
return 1;
|
|
|
|
if( DstAddr.SSN == 0 )
|
|
{
|
|
pIntraMsg->cause = RT_UU;
|
|
spLogDebug ( SCCPDB_ERR, "<013>Invalid SSN(0)" );
|
|
SccpCsta[SccpCstaInd].error[2]++;
|
|
if( ForceAnsi )
|
|
return scrc_rf ( pIntraMsg, 1 );
|
|
else
|
|
return scrc_rf ( pIntraMsg, mtp3_ansiFlag ( DstAddr.NetID ) );
|
|
}
|
|
|
|
if( DstAddr.SSN == 1 ) //scmg message
|
|
return sclc2scmg ( pIntraMsg );
|
|
|
|
#ifdef _WXC_SPTEST_TEMP
|
|
//just for test , delete it for normal
|
|
if( pAddr->ip == INADDR_NONE && pIntraMsg->msgsource == FROM_MTP )
|
|
{
|
|
if( ( pIntraMsg->msgtype >= CR_MSG && pIntraMsg->msgtype <= AK_MSG ) )
|
|
{
|
|
if( ForceAnsi )
|
|
return cr2co ( pIntraMsg, 1 );
|
|
else
|
|
return cr2co ( pIntraMsg, mtp3_ansiFlag ( DstAddr.NetID ) );
|
|
}
|
|
else
|
|
{
|
|
if( MNP_Flag[0] == 0 || pIntraMsg->msgsource != FROM_MTP ) /* MNP not supported */
|
|
return scrc2sclc ( pIntraMsg );
|
|
|
|
/* SCCP Steering Function */
|
|
/* message received or sent */
|
|
/* MNP supported */
|
|
/* routing method */
|
|
pIntraMsg->msgMNP = 0;
|
|
|
|
if( DstAddr.SSN == 6 && DstAddr.NP == 1 && pIntraMsg->data[0] == 0x62 )
|
|
{
|
|
/* IN_Based and SRI for voice call */
|
|
if( MNP_Flag[0] == 1 && DstAddr.TT != 0 )
|
|
{
|
|
pIntraMsg->msgMNP = 0;
|
|
}
|
|
else if( pIntraMsg->CGA.SSN != 10 )
|
|
{
|
|
pIntraMsg->msgMNP = 1;
|
|
}
|
|
return scrc2sclc ( pIntraMsg );
|
|
}
|
|
else
|
|
{
|
|
return scrc2sclc ( pIntraMsg );
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
pAddr->ip = SelectIPOfSSN ( DstAddr.SSN, pIntraMsg->SLS, ( pIntraMsg->msgsource == FROM_MTP ) );
|
|
|
|
if( pAddr->ip == SCCP_Param.ip ) //local Node
|
|
|
|
{
|
|
if( ( pIntraMsg->msgtype >= CR_MSG && pIntraMsg->msgtype <= AK_MSG ) )
|
|
{
|
|
if( ForceAnsi )
|
|
return cr2co ( pIntraMsg, 1 );
|
|
else
|
|
return cr2co ( pIntraMsg, mtp3_ansiFlag ( DstAddr.NetID ) );
|
|
}
|
|
else
|
|
{
|
|
if( sccp_send_netcap)
|
|
{
|
|
int len;
|
|
up_message MsgToMTP;
|
|
int ansi_flag ;
|
|
if( ForceAnsi )
|
|
ansi_flag = 1;
|
|
else
|
|
ansi_flag = mtp3_ansiFlag(DstAddr.NetID);
|
|
|
|
len = build_msg ( MsgToMTP.msgList, pIntraMsg, pIntraMsg->NetID ,ansi_flag );
|
|
MsgToMTP.len = len%256;
|
|
NcSccpSend( MsgToMTP.msgList , MsgToMTP.len , (u8 *)pIntraMsg , ansi_flag);
|
|
}
|
|
|
|
|
|
if( MNP_Flag[0] == 0 || pIntraMsg->msgsource != FROM_MTP ) /* MNP not supported */
|
|
return scrc2sclc ( pIntraMsg );
|
|
|
|
/* SCCP Steering Function */
|
|
/* message received or sent */
|
|
/* MNP supported */
|
|
/* routing method */
|
|
pIntraMsg->msgMNP = 0;
|
|
|
|
if( DstAddr.SSN == 6 && DstAddr.NP == 1 && pIntraMsg->data[0] == 0x62 )
|
|
{
|
|
/* IN_Based and SRI for voice call */
|
|
if( MNP_Flag[0] == 1 && DstAddr.TT != 0 )
|
|
{
|
|
pIntraMsg->msgMNP = 0;
|
|
}
|
|
else if( pIntraMsg->CGA.SSN != 10 )
|
|
{
|
|
pIntraMsg->msgMNP = 1;
|
|
}
|
|
return scrc2sclc ( pIntraMsg );
|
|
}
|
|
else
|
|
{
|
|
return scrc2sclc ( pIntraMsg );
|
|
}
|
|
}
|
|
}
|
|
else if( pAddr->ip == 0 ) //none subsystem is reachable
|
|
{
|
|
pIntraMsg->cause = RT_SF;
|
|
SccpCsta[SccpCstaInd].error[3]++;
|
|
if( ForceAnsi )
|
|
return scrc_rf ( pIntraMsg, 1 );
|
|
else
|
|
return scrc_rf ( pIntraMsg, mtp3_ansiFlag ( DstAddr.NetID ) );
|
|
}
|
|
else //relay to specify subsystem
|
|
{
|
|
snmpLogInfo ( "scrc_route(): start... 327" );
|
|
if( ForceAnsi )
|
|
return send_msg ( pIntraMsg, 1 );
|
|
else
|
|
return send_msg ( pIntraMsg, mtp3_ansiFlag ( DstAddr.NetID ) );
|
|
}
|
|
}
|
|
|
|
int scrc_mnp_route ( Intra_Msg * pIntraMsg, BOOL ForceAnsi )
|
|
{
|
|
SCCP_ADDR *pAddr = NULL, DstAddr;
|
|
SCCP_ROUTE *pRoute = NULL;
|
|
int LocalSPC;
|
|
u_short nRoute = 0xFFFF;
|
|
BYTE Num[32], NumLen;
|
|
BYTE routeAI;
|
|
BYTE field = 0;
|
|
|
|
SccpCsta[SccpCstaInd].utilization[0]++;
|
|
|
|
pAddr = &pIntraMsg->CDA;
|
|
/* daniel */
|
|
pAddr->AI = 1; //default to include DPC
|
|
pIntraMsg->CGA.AI = 1; //default to include DPC
|
|
/* daniel */
|
|
memcpy ( &DstAddr, pAddr, sizeof ( SCCP_ADDR ) );
|
|
|
|
if( pAddr->RI == RI_SSN && pAddr->DPC == 0 )
|
|
{
|
|
if( pAddr->NetID > 3 )
|
|
{
|
|
spLogDebug ( SCCPDB_ERR, "<021>SCCP Translation:SPC not available" );
|
|
SccpCsta[SccpCstaInd].error[0]++;
|
|
return -1;
|
|
}
|
|
DstAddr.DPC = SCCP_Param.spc[pAddr->NetID];
|
|
}
|
|
//Route On GT
|
|
if( DstAddr.RI == RI_GT || DstAddr.DPC == 0 || DstAddr.SSN == 0 || DstAddr.NetID > 3 )
|
|
{
|
|
SccpCsta[SccpCstaInd].utilization[5 - 3]++;
|
|
if( pIntraMsg->CDA.GTI == 0 )
|
|
{
|
|
pIntraMsg->cause = RT_NTFN;
|
|
spLogDebug ( SCCPDB_ERR, "<021>SCCP Translation:GTI == 0 (4 is recommended)" );
|
|
SccpCsta[SccpCstaInd].error[1]++;
|
|
return -1;
|
|
}
|
|
/* if(pIntraMsg->CDA.TT != 0)
|
|
{
|
|
spLogDebug(SCCPDB_ERR, "<012>SCCP Translation:no translation for an address of such nature(TT=%d)", pIntraMsg->CDA.TT);
|
|
pIntraMsg->cause = RT_NTFN;
|
|
SccpCsta[SccpCstaInd].error[0] ++;
|
|
return -1;
|
|
} */
|
|
|
|
if( pAddr->len > ( MAX_DIGITS * 2 ) )
|
|
{
|
|
SCCPCapBuf.watch_dog[0]++;
|
|
sccp_put_capture_logs ( 01, ( BYTE * ) pIntraMsg, sizeof ( Intra_Msg ) );
|
|
spLogDebug ( SCCPDB_ERR, "<024>SCCP Receive Invalid Message,GTT len=%d, the Message was discarded and captured", pAddr->len );
|
|
return -2;
|
|
}
|
|
|
|
if( pAddr->NP > 0 )
|
|
Num[field++] = pAddr->NP;
|
|
else
|
|
Num[field++] = NP_MSISDN;
|
|
if( pAddr->TT > 0 )
|
|
{
|
|
Num[field++] = pAddr->TT / 100;
|
|
Num[field++] = ( pAddr->TT / 10 ) % 10;
|
|
Num[field++] = pAddr->TT % 10;
|
|
}
|
|
else
|
|
{
|
|
Num[field++] = TT_0;
|
|
Num[field++] = TT_1;
|
|
Num[field++] = TT_4;
|
|
}
|
|
NumLen = pAddr->len % ( MAX_DIGITS * 2 );
|
|
Digits2Array ( Num + field, pAddr->GTAI, ( NumLen + 1 ) / 2 );
|
|
nRoute = SelectRoute ( Num, NumLen + field );
|
|
|
|
if( nRoute < SCCP_ROUTE_NUM )
|
|
{
|
|
pRoute = &RouteList[nRoute];
|
|
|
|
if( DstAddr.NetID != pRoute->NetID )
|
|
pIntraMsg->CGA.RI = RI_GT;
|
|
/* daniel */
|
|
else if( pIntraMsg->msgsource != FROM_MTP )
|
|
pIntraMsg->CGA.RI = pRoute->RI;
|
|
/* daniel */
|
|
DstAddr.NetID = pRoute->NetID;
|
|
|
|
if( pRoute->SSN > 0 )
|
|
pAddr->SSN = DstAddr.SSN = pRoute->SSN;
|
|
|
|
pAddr->RI = pRoute->RI;
|
|
DstAddr.DPC = pRoute->DPC[0] * 0x10000 + pRoute->DPC[1] * 0x100 + pRoute->DPC[2];
|
|
|
|
if( pRoute->convert )
|
|
{
|
|
DstAddr.RI = pAddr->RI;
|
|
TranslateGT ( &DstAddr, pRoute );
|
|
memcpy ( pAddr, &DstAddr, sizeof ( SCCP_ADDR ) );
|
|
}
|
|
|
|
/* daniel */
|
|
routeAI = pRoute->AI;
|
|
//set calling address
|
|
if( pIntraMsg->CGA.RI == 0 ) //route on GT
|
|
{
|
|
if( ( routeAI & 1 ) == 0 ) //point code no need
|
|
pIntraMsg->CGA.AI &= ~1; //set dpc=0
|
|
}
|
|
else //route on DPC+SSN
|
|
{
|
|
if( ( routeAI & 4 ) == 0 ) //GT no need
|
|
pIntraMsg->CGA.GTI = 0; //set GT=0
|
|
}
|
|
|
|
//set called address
|
|
if( pAddr->RI == 0 ) //route on GT
|
|
{
|
|
if( ( routeAI & 1 ) == 0 ) //point code no need
|
|
pAddr->AI &= ~1; //set dpc=0
|
|
}
|
|
else //route on DPC+SSN
|
|
{
|
|
if( ( routeAI & 4 ) == 0 ) //GT no need
|
|
pAddr->GTI = 0; //set GTI=0
|
|
}
|
|
/* daniel */
|
|
|
|
}
|
|
else if( nRoute >= 1024 && nRoute < 1024 + 256 ) //local Node
|
|
{
|
|
pAddr->SSN = DstAddr.SSN = nRoute - 1024;
|
|
if( DstAddr.NetID > 3 )
|
|
DstAddr.NetID = LocalSSN[DstAddr.SSN].NetID;
|
|
|
|
pAddr->RI = RI_SSN;
|
|
DstAddr.DPC = SCCP_Param.spc[DstAddr.NetID & 3];
|
|
}
|
|
else
|
|
{
|
|
pIntraMsg->cause = RT_NTFA;
|
|
SccpCsta[SccpCstaInd].avail[1]++;
|
|
if( ForceAnsi )
|
|
return scrc_rf ( pIntraMsg, 1 );
|
|
else
|
|
return scrc_rf ( pIntraMsg, mtp3_ansiFlag ( DstAddr.NetID ) );
|
|
}
|
|
}
|
|
if( !CheckAvail ( &DstAddr ) )
|
|
{
|
|
pIntraMsg->cause = RT_SF;
|
|
if( ForceAnsi )
|
|
return scrc_rf ( pIntraMsg, 1 );
|
|
else
|
|
return scrc_rf ( pIntraMsg, mtp3_ansiFlag ( DstAddr.NetID ) );
|
|
}
|
|
|
|
pIntraMsg->NetID = DstAddr.NetID % 4; //0~3
|
|
pIntraMsg->DPC = pAddr->DPC = DstAddr.DPC;
|
|
LocalSPC = SCCP_Param.spc[pIntraMsg->NetID];
|
|
|
|
if( DstAddr.DPC != LocalSPC )
|
|
{
|
|
snmpLogInfo ( "mnp_scrc_route(): start... 471" );
|
|
|
|
if (pIntraMsg->sequenceFlag == 1 && pIntraMsg->msgtype == UDT_MSG){
|
|
pIntraMsg->SLS = get_sls(pIntraMsg->DPC); //in-sequence delivery, add by Roy Jiang, 07-09-26
|
|
}
|
|
|
|
if( ForceAnsi )
|
|
return send_msg ( pIntraMsg, 1 );
|
|
else
|
|
return send_msg ( pIntraMsg, mtp3_ansiFlag ( DstAddr.NetID ) );
|
|
//snmpLogInfo ( "mnp_scrc_route(): end... 471" );
|
|
}
|
|
else if( pIntraMsg->msgtype == UDTS_MSG ) //discast UDTS message to local node
|
|
return 1;
|
|
|
|
if( DstAddr.SSN == 0 )
|
|
{
|
|
pIntraMsg->cause = RT_UU;
|
|
spLogDebug ( SCCPDB_ERR, "<023>Invalid SSN(0)" );
|
|
SccpCsta[SccpCstaInd].error[2]++;
|
|
if( ForceAnsi )
|
|
return scrc_rf ( pIntraMsg, 1 );
|
|
else
|
|
return scrc_rf ( pIntraMsg, mtp3_ansiFlag ( DstAddr.NetID ) );
|
|
}
|
|
|
|
if( DstAddr.SSN == 1 ) //scmg message
|
|
return sclc2scmg ( pIntraMsg );
|
|
|
|
pAddr->ip = SelectIPOfSSN ( DstAddr.SSN, pIntraMsg->SLS, ( pIntraMsg->msgsource == FROM_MTP ) );
|
|
|
|
pIntraMsg->msgMNP = 0;
|
|
if( pAddr->ip == 0 ) //none subsystem is reachable
|
|
{
|
|
pIntraMsg->cause = RT_SF;
|
|
SccpCsta[SccpCstaInd].error[3]++;
|
|
if( ForceAnsi )
|
|
return scrc_rf ( pIntraMsg, 1 );
|
|
else
|
|
return scrc_rf ( pIntraMsg, mtp3_ansiFlag ( DstAddr.NetID ) );
|
|
}
|
|
else if( pAddr->ip == SCCP_Param.ip ) //local Node
|
|
{
|
|
if( pIntraMsg->msgtype == CR_MSG || ( DstAddr.SSN == SCCP_Param.CO_SSN && SCCP_Param.CO_SSN > 1 ) )
|
|
{
|
|
if( ForceAnsi )
|
|
return cr2co ( pIntraMsg, 1 );
|
|
else
|
|
return cr2co ( pIntraMsg, mtp3_ansiFlag ( DstAddr.NetID ) );
|
|
}
|
|
else
|
|
return scrc2sclc ( pIntraMsg );
|
|
}
|
|
else //relay to specify subsystem
|
|
{
|
|
snmpLogInfo ( "scrc_route(): start... 327" );
|
|
if( ForceAnsi )
|
|
return send_msg ( pIntraMsg, 1 );
|
|
else
|
|
return send_msg ( pIntraMsg, mtp3_ansiFlag ( DstAddr.NetID ) );
|
|
}
|
|
}
|
|
|
|
int send_msg ( Intra_Msg * pIntraMsg, BYTE ansi_flag )
|
|
//pass message to mtp module
|
|
{
|
|
int retval = 0;
|
|
int len = 0;
|
|
up_message MsgToMTP;
|
|
|
|
pIntraMsg->DPC = pIntraMsg->CDA.DPC;
|
|
|
|
if( pIntraMsg->msgsource != FROM_MTP && ( pIntraMsg->SLS & 0x80 ) == 0 )
|
|
{
|
|
if( pIntraMsg->NetID > 3 )
|
|
{
|
|
return 0;
|
|
}
|
|
pIntraMsg->CGA.DPC = SCCP_Param.spc[pIntraMsg->NetID];
|
|
pIntraMsg->OPC = SCCP_Param.spc[pIntraMsg->NetID];
|
|
}
|
|
|
|
snmpLogInfo ( "send_msg(), build_msg: start..." );
|
|
|
|
if( pIntraMsg->msglen > 256 )
|
|
return 0;
|
|
len = build_msg ( MsgToMTP.msgList, pIntraMsg, pIntraMsg->NetID, ansi_flag );
|
|
|
|
/*
|
|
MsgToMTP.len = build_msg ( MsgToMTP.msgList, pIntraMsg, pIntraMsg->NetID );
|
|
if( MsgToMTP.len > 256 ) MsgToMTP.len is a BYTE
|
|
{
|
|
return 0; //added by Pierre, 01-19-05 for core at following line
|
|
}
|
|
|
|
*/
|
|
|
|
//add for UDT SegmentingMsg to XUDT
|
|
if( len < 272 && ( len + 8 ) > 0xfd && pIntraMsg->msgtype == UDT_MSG && pIntraMsg->msgsource == FROM_SCLC
|
|
&& pIntraMsg->CDA.ip != 0 && pIntraMsg->CDA.ip != SCCP_Param.ip && pIntraMsg->CDA.ip != INADDR_NONE )
|
|
{ //relay to special system msg too long ,need cut to segment -- add by lw 2007/03/20
|
|
spLogDebug ( SCCPDB_UDT, "UDT Message form upper layer is too long, [ %d Bytes(len=%d if include MTP3)]! " "Need to be segmented!\r\n ", pIntraMsg->msglen, len );
|
|
retval = SegmentingMsg ( pIntraMsg );
|
|
return retval;
|
|
}
|
|
|
|
if( len >= 256 )
|
|
{
|
|
spLogDebug ( SCCPDB_ERR, "Build SCCP Message too long! " );
|
|
return 0;
|
|
}
|
|
MsgToMTP.len = len % 256;
|
|
snmpLogInfo ( "send_msg(), type message: start..." );
|
|
switch ( pIntraMsg->msgsource )
|
|
{
|
|
case FROM_MTP:
|
|
spShowMsg ( SCCPDB_STP, "SCCP ==> MTP3: STP", pIntraMsg );
|
|
break;
|
|
case FROM_SCLC:
|
|
switch ( pIntraMsg->msgtype )
|
|
{
|
|
case UDT_MSG:
|
|
SccpCsta[SccpCstaInd].quality[0]++;
|
|
spShowMsg ( SCCPDB_UDT, "SCCP ==> MTP3:", pIntraMsg );
|
|
break;
|
|
case UDTS_MSG:
|
|
SccpCsta[SccpCstaInd].quality[1]++;
|
|
spShowMsg ( SCCPDB_UDT, "SCCP ==> MTP3:", pIntraMsg );
|
|
break;
|
|
case XUDT_MSG: //add for UDT SegmentingMsg to XUDT
|
|
spShowMsg ( SCCPDB_XUDT, "SCCP ==> MTP3:", pIntraMsg );
|
|
break;
|
|
case XUDTS_MSG: //add for UDT SegmentingMsg to XUDT
|
|
spShowMsg ( SCCPDB_XUDT, "SCCP ==> MTP3:", pIntraMsg );
|
|
break;
|
|
}
|
|
break;
|
|
case FROM_SCOC:
|
|
spShowMsg ( SCCPDB_AIF, "SCCP ==> MTP3: AIF", pIntraMsg );
|
|
break;
|
|
case FROM_SCMG:
|
|
spShowMsg ( SCCPDB_SCMG, "SCCP ==> MTP3: SCMG", pIntraMsg );
|
|
break;
|
|
}
|
|
|
|
MsgToMTP.dest_ip = pIntraMsg->CDA.ip;
|
|
MsgToMTP.dpc = pIntraMsg->DPC;
|
|
MsgToMTP.opc = pIntraMsg->OPC;
|
|
MsgToMTP.sio = pIntraMsg->NetID * 0x40 + 3;
|
|
MsgToMTP.cic[0] = pIntraMsg->SLS & 0x0F;
|
|
MsgToMTP.link = 0xff;
|
|
|
|
if(pIntraMsg->redirectFlag == 1 && pIntraMsg->CDA.ip != 0xFFFFFFFF) //add by Roy to support sccp dual server message redirect, 07-09-12
|
|
retval = sccp_redirect ( &MsgToMTP );
|
|
else
|
|
retval = sccp_to_mtp3 ( &MsgToMTP );
|
|
|
|
if( sccp_send_netcap)
|
|
{
|
|
NcSccpSend( MsgToMTP.msgList , MsgToMTP.len , (u8 *)pIntraMsg , ansi_flag );
|
|
}
|
|
|
|
return retval;
|
|
// return sccp_to_mtp3(&MsgToMTP); //depend on mtp module
|
|
}
|
|
|
|
int scrc_rf ( Intra_Msg * pIntraMsg, BYTE AnsiFlag )
|
|
{
|
|
#ifdef _WXC_TEST
|
|
WxcAssert ( 0, "routing fail" );
|
|
#endif
|
|
if( isco ( pIntraMsg ) )
|
|
{
|
|
|
|
pIntraMsg->msgtype = SP_MSG_RF;
|
|
cr2co ( pIntraMsg, AnsiFlag );
|
|
spShowMsg ( SCCPDB_ERR, "<006>Route Failure", pIntraMsg );
|
|
return -1;
|
|
}
|
|
else
|
|
return sclc_rf ( pIntraMsg );
|
|
}
|
|
|
|
DWORD SelectIPOfSSN ( BYTE ssn, BYTE sls, BOOL from_mtp )
|
|
{
|
|
LOCAL_SSN *pssn = &LocalSSN[ssn];
|
|
|
|
switch ( pssn->status[0] )
|
|
{
|
|
case ST_Enable:
|
|
switch ( pssn->status[1] )
|
|
{
|
|
case ST_Enable:
|
|
if( pssn->local == 0 )
|
|
return pssn->ip[sls & 0x01];
|
|
else if( from_mtp )
|
|
return pssn->ip[( pssn->local - 1 ) & 0x01];
|
|
else if( ( sls & 0x80 ) == 0x80 )
|
|
return pssn->ip[pssn->local & 0x01];
|
|
else
|
|
return pssn->ip[sls & 0x01];
|
|
//break;
|
|
default:
|
|
if( ( sls & 0x80 ) == 0x80 && pssn->local == 1 )
|
|
{
|
|
spLogDebug ( SCCPDB_ERR, "<014>Message was refused by subsystem_%d_0 and subsystem_%d_1 inaccessible", ssn, ssn );
|
|
return 0;
|
|
}
|
|
else
|
|
return pssn->ip[0];
|
|
//break;
|
|
}
|
|
//break;
|
|
default:
|
|
switch ( pssn->status[1] )
|
|
{
|
|
case ST_Enable:
|
|
if( ( sls & 0x80 ) == 0x80 && pssn->local == 2 )
|
|
{
|
|
spLogDebug ( SCCPDB_ERR, "<015>Message was refused by subsystem_%d_1 and subsystem_%d_0 inaccessible", ssn, ssn );
|
|
return 0;
|
|
}
|
|
else
|
|
return pssn->ip[1];
|
|
//break;
|
|
default:
|
|
spLogDebug ( SCCPDB_ERR, "<016>Subsystem_%d is inaccessible", ssn );
|
|
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
//sequence control functions -- add by Roy Jiang 2007-09-17
|
|
int get_sls(int dpc)
|
|
{
|
|
static int pos = 0; //end position of dpc2sls array
|
|
static u8 next_sls = 0; //sls for new dpc
|
|
int i;
|
|
|
|
for(i=0; i<pos; i++){
|
|
if (dpc2sls[i].dpc == dpc){
|
|
assert(dpc2sls[i].sls != 0xFF);
|
|
return dpc2sls[i].sls;
|
|
}
|
|
}
|
|
|
|
//add dpc to dpc2sls array
|
|
if (pos >= 256)
|
|
return next_sls;
|
|
|
|
dpc2sls[i].dpc = dpc;
|
|
dpc2sls[i].sls = next_sls;
|
|
next_sls = (next_sls + 1) & 0x0F;
|
|
pos++;
|
|
|
|
return dpc2sls[i].sls;
|
|
}
|
|
//end of sequence control functions -- add by Roy Jiang 2007-09-17
|
|
|