Files
svc.ems/plat/sccp/src/scrc.c
2024-09-27 15:39:34 +08:00

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