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