778 lines
26 KiB
C
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;
|
|
}
|