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

778 lines
26 KiB
C

/*****************************************/
/*Title:sccpmsg.c */
/*Descr:SCCP message Procedure */
/*Author: Liang Hanxi */
/*Create: 2002-2-19 */
/*Modify: 2003-5-9 */
/*****************************************/
#include "./include/sccp.h"
/* =========== export ================ */
int build_msg ( BYTE * buf, Intra_Msg * intramsg, BYTE NetID, BYTE ansi_flag );
int parse_msg ( BYTE * buf, Intra_Msg * intramsg, int len, BYTE NetID, BYTE ansi_flag );
/* =========== private ================ */
static int parse_oparam ( BYTE * buf, int len, Intra_Msg * intramsg, BYTE NetID, BYTE ansi_flag );
static int encode_addr ( BYTE * buf, SCCP_ADDR * addr, BYTE NetID );
static int decode_addr ( BYTE * buf, SCCP_ADDR * addr, BYTE NetID );
/* ansi */
static int encode_addr_Ansi ( BYTE * buf, SCCP_ADDR * addr );
static int decode_addr_Ansi ( BYTE * buf, SCCP_ADDR * addr );
/* ansi */
//static int encode_int ( BYTE * buf, unsigned int val, BYTE len );
//static unsigned int decode_int ( BYTE * buf, BYTE len );
extern void spLogDebug ( DWORD mask, const char *fmt, ... );
/* by simon at 23/9/26 */
extern SCCP_Capture_Buf SCCPCapBuf;
extern DWORD SccpCstaInd;
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;
////////////////////////////////////////////////////////////
int build_msg ( BYTE * buf, Intra_Msg * intramsg, BYTE NetID, BYTE ansi_flag )
{
int msglen = 0, vnum = 0, vlen = 0;
buf[msglen++] = intramsg->msgtype;
if( intramsg->msglen > 256 )
{
intramsg->msglen = 256;
}
switch ( intramsg->msgtype )
{
case CR_MSG:
vnum = 1 + 1;
memcpy ( buf + msglen, &intramsg->aSLR, 3 ); //SLR
msglen += 3;
//msglen += encode_int ( buf + msglen, intramsg->aSLR, 3 ); //SLR
buf[msglen++] = intramsg->msgclass; //protocol class
/*Mandatory variable part */
buf[msglen++] = vnum--; //pointer of CDA
if( !ansi_flag )
vlen += encode_addr ( buf + msglen + vnum + vlen, &( intramsg->CDA ), NetID );
else
vlen += encode_addr_Ansi ( buf + msglen + vnum + vlen, &( intramsg->CDA ) );
buf[msglen++] = ( vnum-- ) + vlen; //Pointer of optional part
msglen += vlen;
/*optional part */
/*
buf[msglen++] = P_CGA; //codes of CGA
msglen += encode_addr(buf + msglen, &(intramsg->CGA), NetID);
*/
buf[msglen++] = P_Data;
if( intramsg->msglen > 0 )
{
buf[msglen++] = intramsg->msglen;
memcpy ( buf + msglen, intramsg->data, intramsg->msglen );
msglen += intramsg->msglen;
}
buf[msglen++] = P_EOP;
break;
case CC_MSG:
memcpy ( buf + msglen, &intramsg->aDLR, 3 ); //DLR
msglen += 3;
//msglen += encode_int ( buf + msglen, intramsg->aDLR, 3 );
memcpy ( buf + msglen, &intramsg->aSLR, 3 ); //SLR
msglen += 3;
//msglen += encode_int ( buf + msglen, intramsg->aSLR, 3 );
buf[msglen++] = intramsg->msgclass;
buf[msglen++] = 1; // pointer ot end of optional
buf[msglen++] = 0; // end of optional
break;
case CREF_MSG:
memcpy ( buf + msglen, &intramsg->aDLR, 3 ); //DLR
msglen += 3;
//msglen += encode_int ( buf + msglen, intramsg->aDLR, 3 );
buf[msglen++] = intramsg->cause;
buf[msglen++] = 1; // pointer ot end of optional
buf[msglen++] = 0; // end of optional
break;
case UDT_MSG:
vnum = 3;
buf[msglen++] = intramsg->msgclass;
/*mandatory variable part */
buf[msglen++] = vnum--; //pointer of CDA
if( !ansi_flag )
vlen += ( encode_addr ( buf + msglen + vnum + vlen, &( intramsg->CDA ), NetID ) % 64 );
else
vlen += ( encode_addr_Ansi ( buf + msglen + vnum + vlen, &( intramsg->CDA ) ) % 64 );
buf[msglen++] = ( vnum-- ) + vlen; //Pointer of CGA
if( !ansi_flag )
vlen += ( encode_addr ( buf + msglen + vnum + vlen, &( intramsg->CGA ), NetID ) % 64 );
else
vlen += ( encode_addr_Ansi ( buf + msglen + vnum + vlen, &( intramsg->CGA ) ) % 64 );
buf[msglen++] = ( vnum-- ) + vlen; //Pointer of Data
buf[msglen + vnum + vlen] = intramsg->msglen; //Length of Data
memcpy ( buf + msglen + vnum + vlen + 1, intramsg->data, intramsg->msglen );
vlen = vlen + intramsg->msglen + 1;
msglen += vlen;
break;
case UDTS_MSG:
vnum = 3;
buf[msglen++] = intramsg->cause;
/*mandatory variable part */
buf[msglen++] = vnum--; //pointer of CDA
if( !ansi_flag )
vlen += ( encode_addr ( buf + msglen + vnum + vlen, &( intramsg->CDA ), NetID ) % 64 );
else
vlen += ( encode_addr_Ansi ( buf + msglen + vnum + vlen, &( intramsg->CDA ) ) % 64 );
buf[msglen++] = ( vnum-- ) + vlen; //Pointer of CGA
if( !ansi_flag )
vlen += ( encode_addr ( buf + msglen + vnum + vlen, &( intramsg->CGA ), NetID ) % 64 );
else
vlen += ( encode_addr_Ansi ( buf + msglen + vnum + vlen, &( intramsg->CGA ) ) % 64 );
buf[msglen++] = ( vnum-- ) + vlen; //Pointer of Data
buf[msglen + vnum + vlen] = intramsg->msglen; //Length of Data
memcpy ( buf + msglen + vnum + vlen + 1, intramsg->data, intramsg->msglen );
vlen = vlen + intramsg->msglen + 1;
msglen += vlen;
break;
case XUDT_MSG:
vnum = intramsg->SegPresent ? 4 : 3;
buf[msglen++] = intramsg->msgclass;
buf[msglen++] = intramsg->Hop;
/*mandatory variable part */
buf[msglen++] = vnum--; //pointer of CDA
vlen += ( encode_addr ( buf + msglen + vnum + vlen, &( intramsg->CDA ), NetID ) % 64 );
buf[msglen++] = ( vnum-- ) + vlen; //Pointer of CGA
vlen += ( encode_addr ( buf + msglen + vnum + vlen, &( intramsg->CGA ), NetID ) % 64 );
buf[msglen++] = ( vnum-- ) + vlen; //Pointer of Data
buf[msglen + vnum + vlen] = intramsg->msglen; //Length of Data
memcpy ( buf + msglen + vnum + vlen + 1, intramsg->data, intramsg->msglen );
vlen = vlen + intramsg->msglen + 1;
if( intramsg->SegPresent )
{
buf[msglen++] = ( vnum-- ) + vlen; //Pointer to Segmentation
buf[msglen + vnum + vlen] = P_SEG; //Segmentation tag
buf[msglen + vnum + vlen + 1] = 4; //Segmentation len
memcpy ( buf + msglen + vnum + vlen + 2, &intramsg->Segmnt, 4 );
msglen += 6;
}
msglen += vlen;
break;
case DT1_MSG:
memcpy ( buf + msglen, &intramsg->aDLR, 3 ); //DLR
msglen += 3;
//msglen += encode_int ( buf + msglen, intramsg->aDLR, 3 );
buf[msglen++] = intramsg->EOD;
buf[msglen++] = 1; //Pointer of Data
buf[msglen++] = intramsg->msglen; //Length of Data
memcpy ( buf + msglen, intramsg->data, intramsg->msglen );
msglen += intramsg->msglen;
break;
case DT2_MSG:
memcpy ( buf + msglen, &intramsg->aDLR, 3 ); //DLR
msglen += 3;
//msglen += encode_int ( buf + msglen, intramsg->aDLR, 3 );
buf[msglen++] = 2 * intramsg->PS;
buf[msglen++] = 2 * intramsg->PR + intramsg->EOD;
buf[msglen++] = 1; //Pointer of Data
buf[msglen++] = intramsg->msglen; //Length of Data
memcpy ( buf + msglen, intramsg->data, intramsg->msglen );
msglen += intramsg->msglen;
break;
case RLSD_MSG:
memcpy ( buf + msglen, &intramsg->aDLR, 3 ); //DLR
msglen += 3;
memcpy ( buf + msglen, &intramsg->aSLR, 3 ); //SLR
msglen += 3;
//msglen += encode_int ( buf + msglen, intramsg->aDLR, 3 );
//msglen += encode_int ( buf + msglen, intramsg->aSLR, 3 );
buf[msglen++] = intramsg->cause;
buf[msglen++] = 1; // pointer ot end of optional
buf[msglen++] = 0; // end of optional
break;
case RLC_MSG:
memcpy ( buf + msglen, &intramsg->aDLR, 3 ); //DLR
msglen += 3;
memcpy ( buf + msglen, &intramsg->aSLR, 3 ); //SLR
msglen += 3;
//msglen += encode_int ( buf + msglen, intramsg->aDLR, 3 );
//msglen += encode_int ( buf + msglen, intramsg->aSLR, 3 );
break;
case IT_MSG:
memcpy ( buf + msglen, &intramsg->aDLR, 3 ); //DLR
msglen += 3;
memcpy ( buf + msglen, &intramsg->aSLR, 3 ); //SLR
msglen += 3;
//msglen += encode_int ( buf + msglen, intramsg->aDLR, 3 );
//msglen += encode_int ( buf + msglen, intramsg->aSLR, 3 );
buf[msglen++] = 2; //class = 2
buf[msglen++] = 0; //Sequencing/segmenting octet 0
buf[msglen++] = 0; //Sequencing/segmenting octet 1
buf[msglen++] = 0; //Credit
break;
}
//buf[0] = msglen-1;
return msglen;
}
int parse_msg ( BYTE * buf, Intra_Msg * intramsg, int len, BYTE NetID, BYTE ansi_flag )
{
int pos = 0;
BYTE ptv, vlen;
intramsg->msgtype = buf[pos++];
switch ( intramsg->msgtype )
{
case CR_MSG:
if( len < 4 )
SCCPCapBuf.watch_dog[2]++; //invalid CR message
memcpy ( &intramsg->aSLR, buf + pos, 3 ); //SLR
pos += 3;
//intramsg->aSLR = decode_int ( buf + pos, 3 );
intramsg->msgclass = buf[pos++];
ptv = pos + buf[pos];
pos++;
if( !ansi_flag )
vlen = decode_addr ( buf + ptv, &( intramsg->CDA ), NetID );
else
vlen = decode_addr_Ansi ( buf + ptv, &( intramsg->CDA ) );
if( vlen + ptv >= len )
return 1;
ptv = pos + buf[pos];
pos++;
parse_oparam ( buf + ptv, len - ptv, intramsg, NetID, ansi_flag );
break;
case CC_MSG:
if( len < 8 )
SCCPCapBuf.watch_dog[3]++; //invalid CC message
memcpy ( &intramsg->aDLR, buf + pos, 3 ); //DLR
pos += 3;
memcpy ( &intramsg->aSLR, buf + pos, 3 ); //SLR
pos += 3;
//intramsg->aDLR = decode_int ( buf + pos, 3 );
//pos += 3;
//intramsg->aSLR = decode_int ( buf + pos, 3 );
//pos += 3;
intramsg->msgclass = buf[pos++];
ptv = pos + buf[pos];
/* if (buf[ptv++] == 0x0F)
{
intramsg->msglen = buf[ptv++];
memcpy ( intramsg->data, buf + ptv, intramsg->msglen );
}
*/
parse_oparam ( buf + ptv, len - ptv, intramsg, NetID, ansi_flag );
break;
case CREF_MSG:
if( len < 5 )
SCCPCapBuf.watch_dog[4]++; //invalid CREF message
memcpy ( &intramsg->aDLR, buf + pos, 3 ); //DLR
pos += 3;
//intramsg->aDLR = decode_int ( buf + pos, 3 );
//pos += 3;
intramsg->cause = buf[pos++];
ptv = pos + buf[pos];
parse_oparam ( buf + ptv, len - ptv, intramsg, NetID, ansi_flag );
break;
case UDT_MSG:
if( len < 2 )
SCCPCapBuf.watch_dog[5]++; //invalid UDT message
intramsg->msgclass = buf[pos++];
ptv = pos + buf[pos];
pos++;
if( !ansi_flag )
vlen = decode_addr ( buf + ptv, &( intramsg->CDA ), NetID );
else
vlen = decode_addr_Ansi ( buf + ptv, &( intramsg->CDA ) );
ptv = pos + buf[pos];
pos++;
if( !ansi_flag )
vlen = decode_addr ( buf + ptv, &( intramsg->CGA ), NetID );
else
vlen = decode_addr_Ansi ( buf + ptv, &( intramsg->CGA ) );
ptv = pos + buf[pos];
pos++;
intramsg->msglen = buf[ptv];
memcpy ( intramsg->data, buf + ptv + 1, intramsg->msglen );
break;
case UDTS_MSG:
if( len < 2 )
SCCPCapBuf.watch_dog[6]++; //invalid UDTs message
intramsg->cause = buf[pos++];
ptv = pos + buf[pos];
pos++;
if( !ansi_flag )
vlen = decode_addr ( buf + ptv, &( intramsg->CDA ), NetID );
else
vlen = decode_addr_Ansi ( buf + ptv, &( intramsg->CDA ) );
ptv = pos + buf[pos];
pos++;
if( !ansi_flag )
vlen = decode_addr ( buf + ptv, &( intramsg->CGA ), NetID );
else
vlen = decode_addr_Ansi ( buf + ptv, &( intramsg->CGA ) );
ptv = pos + buf[pos];
pos++;
intramsg->msglen = buf[ptv];
memcpy ( intramsg->data, buf + ptv + 1, intramsg->msglen );
break;
case XUDT_MSG:
//if (len < 2)
// SCCPCapBuf.watch_dog[5]++;//invalid XUDT message
intramsg->msgclass = buf[pos++];
intramsg->Hop = buf[pos++];
ptv = pos + buf[pos];
pos++;
vlen = decode_addr ( buf + ptv, &( intramsg->CDA ), NetID );
ptv = pos + buf[pos];
pos++;
vlen = decode_addr ( buf + ptv, &( intramsg->CGA ), NetID );
if( vlen + ptv >= len )
return 1;
ptv = pos + buf[pos];
pos = ptv;
intramsg->msglen = buf[pos++];
memcpy ( intramsg->data, buf + pos, intramsg->msglen );
pos += intramsg->msglen;
parse_oparam ( buf + pos, len - pos, intramsg, NetID, ansi_flag );
break;
case DT1_MSG:
if( len < 5 )
SCCPCapBuf.watch_dog[7]++; //invalid DT1 message
memcpy ( &intramsg->aDLR, buf + pos, 3 ); //DLR
pos += 3;
//intramsg->aDLR = decode_int ( buf + pos, 3 );
//pos += 3;
intramsg->EOD = buf[pos++];
ptv = pos + buf[pos];
pos++;
intramsg->msglen = buf[ptv];
memcpy ( intramsg->data, buf + ptv + 1, intramsg->msglen );
break;
case DT2_MSG:
if( len < 7 )
SCCPCapBuf.watch_dog[8]++; //invalid DT2 message
memcpy ( &intramsg->aDLR, buf + pos, 3 ); //DLR
pos += 3;
//intramsg->aDLR = decode_int ( buf + pos, 3 );
//pos += 3;
intramsg->PS = buf[pos++] / 2;
intramsg->PR = buf[pos] / 2;
intramsg->EOD = buf[pos++] % 2;
ptv = pos + buf[pos];
pos++;
intramsg->msglen = buf[ptv];
memcpy ( intramsg->data, buf + ptv + 1, intramsg->msglen );
break;
case RLSD_MSG:
if( len < 8 )
SCCPCapBuf.watch_dog[9]++; //invalid RLSD message
memcpy ( &intramsg->aDLR, buf + pos, 3 ); //DLR
pos += 3;
memcpy ( &intramsg->aSLR, buf + pos, 3 ); //SLR
pos += 3;
//intramsg->aDLR = decode_int ( buf + pos, 3 );
//pos += 3;
//intramsg->aSLR = decode_int ( buf + pos, 3 );
//pos += 3;
intramsg->cause = buf[pos++];
break;
case RLC_MSG:
if( len < 7 )
SCCPCapBuf.watch_dog[10]++; //invalid RLC message
memcpy ( &intramsg->aDLR, buf + pos, 3 ); //DLR
pos += 3;
memcpy ( &intramsg->aSLR, buf + pos, 3 ); //SLR
pos += 3;
//intramsg->aDLR = decode_int ( buf + pos, 3 );
//pos += 3;
//intramsg->aSLR = decode_int ( buf + pos, 3 );
//pos += 3;
break;
case IT_MSG:
if( len < 8 )
SCCPCapBuf.watch_dog[11]++; //invalid IT message
memcpy ( &intramsg->aDLR, buf + pos, 3 ); //DLR
pos += 3;
memcpy ( &intramsg->aSLR, buf + pos, 3 ); //SLR
pos += 3;
//intramsg->aDLR = decode_int ( buf + pos, 3 );
//pos += 3;
//intramsg->aSLR = decode_int ( buf + pos, 3 );
//pos += 3;
intramsg->msgclass = buf[pos++];
break;
}
return 1;
}
int parse_oparam ( BYTE * buf, int len, Intra_Msg * intramsg, BYTE NetID, BYTE ansi_flag )
{
int pos = 0;
BYTE nparam;
while ( pos < len )
{
nparam = buf[pos++];
switch ( nparam )
{
case P_EOP:
return 1;
case P_CDA:
/* if (!ansi_flag)
pos += decode_addr(buf + pos, &(intramsg->CDA), NetID);
else
pos += decode_addr_Ansi(buf + pos, &(intramsg->CDA)); */
break;
case P_CGA:
if( !ansi_flag )
pos += decode_addr ( buf + pos, &( intramsg->CGA ), NetID );
else
pos += decode_addr_Ansi ( buf + pos, &( intramsg->CGA ) );
break;
case P_Data:
intramsg->msglen = buf[pos++];
memcpy ( intramsg->data, buf + pos, intramsg->msglen );
pos += intramsg->msglen;
break;
case P_SEG:
if( buf[pos] != 4 )
{
spLogDebug ( SCCPDB_USER, "SCCP XUDT Msg Segmentaion Parameters length error!" );
}
pos++;
memcpy ( &intramsg->Segmnt, &buf[pos], 4 );
intramsg->SegPresent = 1;
pos += 4;
break;
case P_DLR:
case P_SLR:
case P_PLC:
case P_EOD:
case P_PR:
case P_SEQ:
case P_Credit:
case P_RLC:
case P_RTC:
case P_RSC:
case P_ERC:
case P_RFC:
case P_HC:
case P_Importance:
case P_Ldata:
break;
}
}
return 1;
}
/*
int encode_int ( BYTE * buf, unsigned int val, BYTE len )
{
BYTE temp[4];
temp[0] = ( BYTE ) ( ( val & 0xFF000000 ) >> 24 );
temp[1] = ( BYTE ) ( ( val & 0xFF0000 ) >> 16 );
temp[2] = ( BYTE ) ( ( val & 0xFF00 ) >> 8 );
temp[3] = ( BYTE ) ( val & 0xFF );
memcpy ( buf, temp + 4 - len, len );
return len;
}
unsigned int decode_int ( BYTE * buf, BYTE len )
{
unsigned int rtn = 0, i;
for ( i = 0; i < len; i++ )
rtn = rtn << 8 | buf[i];
return rtn;
}
*/
int encode_addr ( BYTE * buf, SCCP_ADDR * addr, BYTE NetID )
{
BYTE len = 0, cp_len;
BYTE RI_MASK = 0x40, SSN_MASK = 0x02, DPC_MASK = 0x01, GT_MASK = 0x04;
/*GTI*/ len = 2;
//if(addr->RI == RI_SSN && addr->SSN > 0)
// addr->GTI = 0;
buf[1] = ( RI_MASK * addr->RI ) | ( SSN_MASK ) | ( DPC_MASK & ( addr->DPC > 0 ? 1 : 0 ) & ( addr->AI & 1 ) ) | ( GT_MASK * addr->GTI );
if( ( addr->DPC > 0 ) & ( addr->AI & 1 ) )
{
memcpy ( buf + len, ( BYTE * ) & addr->DPC, SCCP_Param.spclen[NetID] );
len += SCCP_Param.spclen[NetID];
}
buf[len++] = addr->SSN;
switch ( addr->GTI )
{
case 0: //no global title included
break;
case 1: //global title includes nature of address indicator only
buf[len++] = addr->NAI;
memcpy ( buf + len, addr->GTAI, ( addr->len + 1 ) / 2 );
len += ( addr->len + 1 ) / 2;
break;
case 2: //global title includes translation type only
buf[len++] = addr->TT;
memcpy ( buf + len, addr->GTAI, ( addr->len + 1 ) / 2 );
len += ( addr->len + 1 ) / 2;
break;
case 3: //global title includes translation type, NP, EC
buf[len++] = addr->TT;
cp_len = ( addr->len + 1 ) / 2;
if( addr->len & 1 ) //odd number of address signals
{
addr->ES = 1;
addr->GTAI[cp_len - 1] = addr->GTAI[cp_len - 1] & 0x0F;
}
else
addr->ES = 2;
buf[len++] = addr->NP * 16 + addr->ES;
addr->GTAI[len] = 0;
memcpy ( buf + len, addr->GTAI, cp_len );
len += cp_len;
break;
case 4: //global title includes translation type, NP, EC, NAI
buf[len++] = addr->TT;
addr->len %= 18;
cp_len = ( addr->len + 1 ) / 2;
if( addr->len & 1 ) //odd number of address signals
{
addr->ES = 1;
addr->GTAI[cp_len - 1] = addr->GTAI[cp_len - 1] & 0x0F;
}
else
addr->ES = 2;
buf[len++] = addr->NP * 16 + addr->ES;
buf[len++] = addr->NAI;
memcpy ( buf + len, addr->GTAI, cp_len );
len += cp_len;
break;
}
buf[0] = len - 1;
return len;
}
int decode_addr ( BYTE * buf, SCCP_ADDR * addr, BYTE NetID )
{
BYTE len, pos, nbyte;
BYTE RI_MASK = 0x40, SSN_MASK = 0x02, DPC_MASK = 0x01, GT_MASK = 0x3C;
BYTE DPCI;
len = buf[0] + 1;
addr->RI = ( buf[1] & RI_MASK ) >> 6;
addr->GTI = ( buf[1] & GT_MASK ) >> 2;
DPCI = ( buf[1] & DPC_MASK );
addr->SSN = ( buf[1] & SSN_MASK ) >> 1;
pos = 2;
if( DPCI )
{
memcpy ( ( BYTE * ) & addr->DPC, buf + pos, SCCP_Param.spclen[NetID] );
pos += SCCP_Param.spclen[NetID];
}
if( addr->SSN )
addr->SSN = buf[pos++];
switch ( addr->GTI )
{
case 0: //no global title included
break;
case 1: //global title includes nature of address indicator only
addr->NAI = buf[pos++] & 0x7F;
nbyte = len - pos;
addr->len = 2 * nbyte;
if( ( buf[pos - 1] & 0x80 ) == 0x80 ) //odd number of address signals
addr->len--;
memcpy ( addr->GTAI, buf + pos, nbyte % ( MAX_DIGITS + 1 ) );
break;
case 2: //global title includes translation type only
addr->TT = buf[pos++];
nbyte = len - pos;
addr->len = 2 * nbyte;
memcpy ( addr->GTAI, buf + pos, nbyte % ( MAX_DIGITS + 1 ) );
break;
case 3: //global title includes translation type, NP, EC
addr->TT = buf[pos++];
addr->NP = buf[pos] / 16;
addr->ES = buf[pos++] % 16;
nbyte = len - pos;
addr->len = 2 * nbyte;
if( addr->ES == 1 )
addr->len--;
memcpy ( addr->GTAI, buf + pos, nbyte % ( MAX_DIGITS + 1 ) );
break;
case 4: //global title includes translation type, NP, EC, NAI
addr->TT = buf[pos++];
addr->NP = buf[pos] / 16;
addr->ES = buf[pos++] % 16;
addr->NAI = buf[pos++] & 0x7F;
nbyte = len - pos;
addr->len = 2 * nbyte;
if( addr->ES == 1 )
addr->len--;
memcpy ( addr->GTAI, buf + pos, nbyte % ( MAX_DIGITS + 1 ) );
break;
}
return len;
}
//----->ansi
int encode_addr_Ansi ( BYTE * buf, SCCP_ADDR * addr )
{
BYTE len = 0, cp_len;
BYTE NAT_MASK = 0x80, RI_MASK = 0x40, DPC_MASK = 0x02, SSN_MASK = 0x01, GT_MASK = 0x04;
BYTE spclen = 3; //ansi is always 24 bit,3 bytes
/*GTI*/ len = 2;
//if(addr->RI == RI_SSN && addr->SSN > 0)
// addr->GTI = 0;
switch ( addr->GTI )
{
case 4:
addr->GTI = 2;
break;
default:
break;
}
buf[1] = NAT_MASK | ( RI_MASK * addr->RI ) | ( SSN_MASK ) | ( DPC_MASK & ( ( addr->DPC > 0 ? 1 : 0 ) * 2 ) & ( ( addr->AI & 1 ) * 2 ) ) | ( GT_MASK * addr->GTI );
buf[len++] = addr->SSN;
if( addr->DPC > 0 && ( addr->AI & 1 ) )
{
/* memcpy(buf + len, (BYTE *)&addr->DPC, SCCP_Param.spclen[NetID]);
len += SCCP_Param.spclen[NetID]; */
memcpy ( buf + len, ( BYTE * ) & addr->DPC, spclen );
len += spclen;
}
switch ( addr->GTI )
{
case 0: //no global title included
break;
case 1: //global title includes translation type, NP, EC
buf[len++] = addr->TT;
cp_len = ( addr->len + 1 ) / 2;
if( addr->len & 1 ) //odd number of address signals
{
addr->ES = 1;
addr->GTAI[cp_len - 1] = addr->GTAI[cp_len - 1] & 0x0F;
}
else
addr->ES = 2;
buf[len++] = addr->NP * 16 + addr->ES;
addr->GTAI[len] = 0;
memcpy ( buf + len, addr->GTAI, cp_len );
len += cp_len;
break;
case 2: //global title includes translation type only
buf[len++] = addr->TT;
/* added by Pierre, 2006-09-30 for the filler */
cp_len = ( addr->len + 1 ) / 2;
if( addr->len & 1 ) //odd number of address signals
{
addr->GTAI[cp_len - 1] = addr->GTAI[cp_len - 1] & 0x0F;
}
/* above lines added by Pierre */
memcpy ( buf + len, addr->GTAI, ( addr->len + 1 ) / 2 );
len += ( addr->len + 1 ) / 2;
break;
default:
break;
}
buf[0] = len - 1;
return len;
}
int decode_addr_Ansi ( BYTE * buf, SCCP_ADDR * addr )
{
BYTE len, pos, nbyte;
BYTE RI_MASK = 0x40, DPC_MASK = 0x02, SSN_MASK = 0x01, GT_MASK = 0x3C;
BYTE DPCI;
BYTE spclen = 3; //ansi is always 24 bit,3 bytes
len = buf[0] + 1;
addr->RI = ( buf[1] & RI_MASK ) >> 6;
addr->GTI = ( buf[1] & GT_MASK ) >> 2;
DPCI = ( buf[1] & DPC_MASK ) >> 1;
addr->SSN = ( buf[1] & SSN_MASK );
pos = 2;
if( addr->SSN )
addr->SSN = buf[pos++];
if( DPCI )
{
/* memcpy((BYTE *)&addr->DPC, buf + pos, SCCP_Param.spclen[NetID]);
pos += SCCP_Param.spclen[NetID]; */
memcpy ( ( BYTE * ) & addr->DPC, buf + pos, spclen );
pos += spclen;
}
switch ( addr->GTI )
{
case 0: //no global title included
break;
case 1: //global title includes translation type, NP, EC
addr->TT = buf[pos++];
addr->NP = buf[pos] / 16;
addr->ES = buf[pos++] % 16;
nbyte = len - pos;
addr->len = 2 * nbyte;
if( addr->ES == 1 )
addr->len--;
memcpy ( addr->GTAI, buf + pos, nbyte % ( MAX_DIGITS + 1 ) );
break;
case 2: //global title includes translation type only
addr->TT = buf[pos++];
nbyte = len - pos;
addr->len = 2 * nbyte;
memcpy ( addr->GTAI, buf + pos, nbyte % ( MAX_DIGITS + 1 ) );
break;
default:
break;
}
return len;
}