418 lines
12 KiB
C
418 lines
12 KiB
C
/****************************************************/
|
|
/*Title: gtt.c */
|
|
/*Descr: GTT Table Management */
|
|
/*Author: Liang Hanxi */
|
|
/*Create: 2002-2-19 */
|
|
/*Modify: 2003-4-30 */
|
|
/****************************************************/
|
|
#include "./include/sccp.h"
|
|
|
|
/*===========export================*/
|
|
int BuildRouteIndex ( );
|
|
u_short SelectRoute ( BYTE * pDigits, BYTE DigitsLen );
|
|
void TranslateGT ( SCCP_ADDR * addr, SCCP_ROUTE * pRoute );
|
|
|
|
/*===========import================*/
|
|
extern void spLog ( char *info );
|
|
extern int ParseLine ( char *str, char ( *row )[128], int maxrow );
|
|
extern int Digits2Array ( BYTE * pArray, BYTE * pDigits, int DigitsLen );
|
|
extern int Bcd2Array ( BYTE * pArray, BYTE * pBcd, int BcdLen );
|
|
extern int Array2Digits ( BYTE * pDigits, BYTE * pArray, int ArrayLen );
|
|
|
|
/* by simon at 23/9/26*/
|
|
extern int RelatedSSNNum;
|
|
extern RL_SSN RelatedSSN[SCCP_RLSSN_NUM];
|
|
extern SCOC_BUF ScocBuf;
|
|
extern SCCP_ROUTE RouteList[SCCP_ROUTE_NUM];
|
|
extern LOCAL_SSN LocalSSN[256];
|
|
extern SCCP_ROUTE RouteList[SCCP_ROUTE_NUM];
|
|
extern SCCP_OPT SCCP_Param;
|
|
|
|
/*===========private================*/
|
|
static int AddRoute ( BYTE * pStartDigits, BYTE * pEndDigits, BYTE DigitsLen, u_short index );
|
|
static int AddLargerNode ( SCCP_ROUTE_NODE * pNode, BYTE * pDigits, BYTE DigitsLen, u_short index );
|
|
static int AddLessNode ( SCCP_ROUTE_NODE * pNode, BYTE * pDigits, BYTE DigitsLen, u_short index );
|
|
static SCCP_ROUTE_NODE *NewNode ( );
|
|
|
|
static SCCP_ROUTE_NODE RouteNode[SCCP_ROUTE_NODE_NUM];
|
|
static SCCP_ROUTE_NODE *pHead = &RouteNode[0];
|
|
static u_short heap_index = 1, item_index = 0;
|
|
|
|
int BuildRouteIndex ( )
|
|
{
|
|
int i;
|
|
BYTE StartNum[32], EndNum[32], NumLen;
|
|
BYTE TTmod10, TTdiv10, TTdiv100;
|
|
BYTE field = 0;
|
|
|
|
TTmod10 = TTdiv10 = TTdiv100 = 0;
|
|
spLog ( "Build GTT Index..." );
|
|
memset ( &RouteNode[0], 0, SCCP_ROUTE_NODE_NUM * sizeof ( SCCP_ROUTE_NODE ) );
|
|
heap_index = 1;
|
|
item_index = 0;
|
|
|
|
for ( i = 2; i < 256; i++ )
|
|
{
|
|
field = 0;
|
|
if( LocalSSN[i].status[0] == 0 && LocalSSN[i].status[1] == 0 )
|
|
continue;
|
|
if( LocalSSN[i].msisdn_len < 1 )
|
|
continue;
|
|
// if (mtp3_ansiFlag(LocalSSN[i].NetID) != 1)/* ITU */
|
|
StartNum[field++] = NP_MSISDN;
|
|
// else
|
|
{ //ANSI
|
|
StartNum[field++] = TT_0;
|
|
StartNum[field++] = TT_1;
|
|
StartNum[field++] = TT_4;
|
|
}
|
|
NumLen = Bcd2Array ( StartNum + field, LocalSSN[i].msisdn, LocalSSN[i].msisdn_len % MAX_DIGITS ) + field;
|
|
if( NumLen < 2 || NumLen > 26 )
|
|
continue;
|
|
if( StartNum[NumLen - 1] > 9 )
|
|
NumLen--;
|
|
|
|
if( AddRoute ( StartNum, StartNum, NumLen, 1024 + i ) == 0 )
|
|
spLog ( "Error: Fail to add local node, resource limit..." );
|
|
}
|
|
|
|
field = 0;
|
|
for ( i = 0; i < SCCP_ROUTE_NUM; i++ )
|
|
{
|
|
if( RouteList[i].avail == 0 )
|
|
continue;
|
|
|
|
TTmod10 = RouteList[i].TT % 10;
|
|
TTdiv10 = ( RouteList[i].TT / 10 ) % 10;
|
|
TTdiv100 = RouteList[i].TT / 100;
|
|
|
|
field = 0;
|
|
if( RouteList[i].NP != 0 )
|
|
StartNum[field++] = RouteList[i].NP;
|
|
else
|
|
StartNum[field++] = NP_MSISDN;
|
|
if( RouteList[i].TT != 0 )
|
|
{
|
|
StartNum[field++] = TTdiv100;
|
|
StartNum[field++] = TTdiv10;
|
|
StartNum[field++] = TTmod10;
|
|
}
|
|
else
|
|
{
|
|
StartNum[field++] = TT_0;
|
|
StartNum[field++] = TT_1;
|
|
StartNum[field++] = TT_4;
|
|
}
|
|
|
|
field = 0;
|
|
if( RouteList[i].NP != 0 )
|
|
EndNum[field++] = RouteList[i].NP;
|
|
else
|
|
EndNum[field++] = NP_MSISDN;
|
|
if( RouteList[i].TT != 0 )
|
|
{
|
|
EndNum[field++] = TTdiv100;
|
|
EndNum[field++] = TTdiv10;
|
|
EndNum[field++] = TTmod10;
|
|
}
|
|
else
|
|
{
|
|
EndNum[field++] = TT_0;
|
|
EndNum[field++] = TT_1;
|
|
EndNum[field++] = TT_4;
|
|
}
|
|
|
|
NumLen = Bcd2Array ( StartNum + field, RouteList[i].StartDigits, RouteList[i].len % MAX_DIGITS ) + field;
|
|
if( NumLen < 2 || NumLen > 26 )
|
|
continue;
|
|
if( StartNum[NumLen - 1] > 9 )
|
|
NumLen--;
|
|
Bcd2Array ( EndNum + field, RouteList[i].EndDigits, RouteList[i].len );
|
|
|
|
if( AddRoute ( StartNum, EndNum, NumLen, i ) == 0 ){
|
|
spLog ( "Error: Fail to add route, resource limit..." );
|
|
break;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
u_short SelectRoute ( BYTE * pDigits, BYTE DigitsLen )
|
|
{
|
|
SCCP_ROUTE_NODE *pNode = pHead;
|
|
int i;
|
|
u_short result = 0xFFFF;
|
|
BYTE num;
|
|
|
|
for ( i = 0; i < DigitsLen; i++ )
|
|
{
|
|
num = pDigits[i];
|
|
if( pNode->psub[num] >= &RouteNode[0] && pNode->psub[num] <= &RouteNode[SCCP_ROUTE_NODE_NUM-1] )
|
|
{
|
|
pNode = pNode->psub[num];
|
|
if( pNode->nItem != 0xFFFF )
|
|
result = pNode->nItem;
|
|
}
|
|
else
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
int GetACNInfo ( SCCP_ADDR * pAddr, BYTE ** pAcnInfo )
|
|
{
|
|
DWORD spc;
|
|
u_short nRoute = 0xFFFF;
|
|
BYTE Num[MAX_DIGITS * 2], NumLen;
|
|
BYTE NetID;
|
|
BYTE field = 0;
|
|
|
|
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 );
|
|
if( pAddr->GTI )
|
|
{
|
|
nRoute = SelectRoute ( Num, NumLen + field );
|
|
if( nRoute < SCCP_ROUTE_NUM )
|
|
{
|
|
if( pAddr->NetID > 3 )
|
|
NetID = RouteList[nRoute].NetID;
|
|
else
|
|
NetID = pAddr->NetID;
|
|
|
|
spc = RouteList[nRoute].DPC[0] * 0x10000 + RouteList[nRoute].DPC[1] * 0x100 + RouteList[nRoute].DPC[2];
|
|
}
|
|
else if( nRoute >= 1024 && nRoute < 1024 + 256 )
|
|
{
|
|
if( pAddr->NetID > 3 )
|
|
NetID = LocalSSN[nRoute - 1024].NetID % 4;
|
|
else
|
|
NetID = pAddr->NetID;
|
|
|
|
spc = SCCP_Param.spc[NetID];
|
|
}
|
|
else
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
NetID = pAddr->NetID;
|
|
spc = pAddr->DPC;
|
|
}
|
|
|
|
*pAcnInfo = spc_to_acn ( NetID, spc );
|
|
if( *pAcnInfo == NULL )
|
|
return 0;
|
|
return 36;
|
|
}
|
|
|
|
void TranslateGT ( SCCP_ADDR * pAddr, SCCP_ROUTE * pRoute )
|
|
{
|
|
BYTE swap[MAX_DIGITS * 2], temp[MAX_DIGITS * 2];
|
|
BYTE ReplaceNum[MAX_DIGITS * 2], len;
|
|
BYTE ReplaceEnd;
|
|
|
|
len = Bcd2Array ( ReplaceNum, pRoute->ReplaceDigits, pRoute->replace_len % MAX_DIGITS );
|
|
|
|
Digits2Array ( temp, pAddr->GTAI, ( ( pAddr->len + 1 ) / 2 ) % MAX_DIGITS );
|
|
|
|
pAddr->NP = NP_GT;
|
|
if( pRoute->ReplaceStart > 1 )
|
|
{
|
|
memcpy ( swap, temp, pRoute->ReplaceStart - 1 );
|
|
}
|
|
|
|
memcpy ( swap + pRoute->ReplaceStart - 1, ReplaceNum, len );
|
|
|
|
ReplaceEnd = pRoute->ReplaceEnd;
|
|
if( pAddr->len < ReplaceEnd )
|
|
ReplaceEnd = pAddr->len;
|
|
|
|
memcpy ( swap + pRoute->ReplaceStart - 1 + len, temp + ReplaceEnd, ( pAddr->len - ReplaceEnd ) % 16 );
|
|
|
|
pAddr->len = pRoute->ReplaceStart - 1 + len + pAddr->len - ReplaceEnd;
|
|
pAddr->NP = pRoute->OutNP;
|
|
Array2Digits ( pAddr->GTAI, swap, pAddr->len );
|
|
}
|
|
|
|
int AddRoute ( BYTE * pStartDigits, BYTE * pEndDigits, BYTE DigitsLen, u_short index )
|
|
{
|
|
SCCP_ROUTE_NODE *pNode = pHead;
|
|
int i, j;
|
|
BYTE startNum, endNum;
|
|
|
|
for ( i = 0; i < DigitsLen; i++ )
|
|
{
|
|
startNum = pStartDigits[i] % 10;
|
|
endNum = pEndDigits[i] % 10;
|
|
if( startNum < endNum )
|
|
{
|
|
for ( j = startNum + 1; j < endNum; j++ )
|
|
{
|
|
if( pNode->psub[j] == NULL && ( pNode->psub[j] = NewNode ( ) ) == NULL )
|
|
return 0;
|
|
|
|
/* add by daniel on 2006-5-15 */
|
|
if( pNode->psub[j]->nItem == 0xFFFF ) //if this node has empty index then mark it with the new index, else do nothing
|
|
/* add by daniel on 2006-5-15 */
|
|
pNode->psub[j]->nItem = index;
|
|
}
|
|
if( pNode->psub[startNum] == NULL && ( pNode->psub[startNum] = NewNode ( ) ) == NULL )
|
|
return 0;
|
|
if( pNode->psub[endNum] == NULL && ( pNode->psub[endNum] = NewNode ( ) ) == NULL )
|
|
return 0;
|
|
if( AddLargerNode ( pNode->psub[startNum], pStartDigits + i + 1, DigitsLen - i - 1, index ) == 0 )
|
|
return 0;
|
|
|
|
if( AddLessNode ( pNode->psub[endNum], pEndDigits + i + 1, DigitsLen - i - 1, index ) == 0 )
|
|
return 0;
|
|
return 1;
|
|
}
|
|
else if( startNum == endNum )
|
|
{
|
|
if( pNode->psub[startNum] == NULL && ( pNode->psub[startNum] = NewNode ( ) ) == NULL )
|
|
{
|
|
//send alarm here
|
|
pNode = NULL;
|
|
return 0;
|
|
}
|
|
pNode = pNode->psub[startNum];
|
|
|
|
if( i >= DigitsLen - 1 )
|
|
{
|
|
pNode->nItem = index;
|
|
return 1;
|
|
}
|
|
continue;
|
|
}
|
|
else if( startNum > endNum )
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int AddLargerNode ( SCCP_ROUTE_NODE * pNode, BYTE * pDigits, BYTE DigitsLen, u_short index )
|
|
{
|
|
int i, j;
|
|
BYTE startNum;
|
|
|
|
for ( i = 0; i < DigitsLen; i++ )
|
|
{
|
|
startNum = pDigits[i] % 10;
|
|
for ( j = startNum + 1; j <= 9; j++ )
|
|
{
|
|
if( pNode->psub[j] == NULL && ( pNode->psub[j] = NewNode ( ) ) == NULL )
|
|
return 0;
|
|
/* add by daniel on 2006-5-15 */
|
|
if( pNode->psub[j]->nItem == 0xFFFF ) //if this node has empty index then mark it with the new index, else do nothing
|
|
/* add by daniel on 2006-5-15 */
|
|
pNode->psub[j]->nItem = index;
|
|
}
|
|
if( pNode->psub[startNum] == NULL && ( pNode->psub[startNum] = NewNode ( ) ) == NULL )
|
|
return 0;
|
|
pNode = pNode->psub[startNum];
|
|
}
|
|
|
|
pNode->nItem = index;
|
|
return 1;
|
|
}
|
|
|
|
int AddLessNode ( SCCP_ROUTE_NODE * pNode, BYTE * pDigits, BYTE DigitsLen, u_short index )
|
|
{
|
|
int i, j;
|
|
BYTE endNum;
|
|
|
|
for ( i = 0; i < DigitsLen; i++ )
|
|
{
|
|
endNum = pDigits[i] % 10;
|
|
for ( j = 0; j < endNum; j++ )
|
|
{
|
|
if( pNode->psub[j] == NULL && ( pNode->psub[j] = NewNode ( ) ) == NULL )
|
|
return 0;
|
|
/* add by daniel on 2006-5-15 */
|
|
if( pNode->psub[j]->nItem == 0xFFFF ) //if this node has empty index then mark it with the new index, else do nothing
|
|
/* add by daniel on 2006-5-15 */
|
|
pNode->psub[j]->nItem = index;
|
|
}
|
|
if( pNode->psub[endNum] == NULL && ( pNode->psub[endNum] = NewNode ( ) ) == NULL )
|
|
return 0;
|
|
|
|
pNode = pNode->psub[endNum];
|
|
}
|
|
pNode->nItem = index;
|
|
return 1;
|
|
}
|
|
|
|
SCCP_ROUTE_NODE *NewNode ( )
|
|
{
|
|
if( heap_index >= SCCP_ROUTE_NODE_NUM ){
|
|
spLog ( "Fatal Error: Fail to add GT node, no resource" );
|
|
return NULL;
|
|
}
|
|
|
|
RouteNode[heap_index].nItem = 0xFFFF;
|
|
return &RouteNode[heap_index++];
|
|
}
|
|
|
|
/*
|
|
*Purpose: check whether a GT is in the SCCP GT table
|
|
*Param: np: Number Plan
|
|
* tt: Translation Type
|
|
* gt: Global title
|
|
* gt_len: length of gt
|
|
*Return: 0 - the GT is not in SCCP GTT
|
|
* 1 - the GT is in SCCP GTT
|
|
*/
|
|
int CheckGT(BYTE np, BYTE tt, BYTE *gt, BYTE gt_len)
|
|
{
|
|
BYTE Num[32], NumLen;
|
|
BYTE field = 0;
|
|
int nRoute;
|
|
|
|
assert(gt_len < 32);
|
|
assert(gt != NULL);
|
|
|
|
if( np > 0 )
|
|
Num[field++] = np;
|
|
else
|
|
Num[field++] = NP_MSISDN;
|
|
|
|
if( tt > 0 )
|
|
{
|
|
Num[field++] = tt / 100;
|
|
Num[field++] = ( tt / 10 ) % 10;
|
|
Num[field++] = tt % 10;
|
|
}
|
|
else
|
|
{
|
|
Num[field++] = TT_0;
|
|
Num[field++] = TT_1;
|
|
Num[field++] = TT_4;
|
|
}
|
|
NumLen = gt_len % ( MAX_DIGITS * 2 );
|
|
Digits2Array ( Num + field, gt, ( NumLen + 1 ) / 2 );
|
|
|
|
nRoute = SelectRoute ( Num, NumLen + field );
|
|
if( nRoute < SCCP_ROUTE_NUM )
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|