/****************************************************/ /*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; }