////////////////////////////////////////////////// //Title : wxc_netcap.c //Auhtor : Liu Wei //Desc : wxc2 netcap implementation //Created : 2007-06-05 //Revision : // //Revision : // ////////////////////////////////////////////////// #include "./include/pub_netcap.h" /*@ignore@*/ #ifndef IPPROTO_SCTP #define IPPROTO_SCTP 132 #endif static NetCap tNC; #define BASE 65521 static u32 NcAd32 ( u32 ad, u8 * buf, int len ) { u32 s1 = ad & 0xffff; u32 s2 = ( ad >> 16 ) & 0xffff; int n; for ( n = 0; n < len; n++, buf++ ) { s1 = ( s1 + *buf ); if ( s1 >= BASE ) s1 -= BASE; s2 = ( s2 + s1 ); if ( s2 >= BASE ) { s2 -= BASE; } } return ( s2 << 16 ) + s1; } #define HEADER_LEN 12 static u32 NcCS ( u8 * ptr, u16 count ) { u32 ad = 1L; u32 zero = 0L; ad = NcAd32 ( ad, ptr, sizeof ( HEADER_LEN - sizeof ( u32 ) ) ); ad = NcAd32 ( ad, ( u8 * ) & zero, sizeof ( u32 ) ); ptr += HEADER_LEN; count -= HEADER_LEN; ad = NcAd32 ( ad, ptr, count ); return ad; } static int NcGetSocket ( u32 port ) { int nSock; int nOn = 1; unsigned long cmdarg = 1; struct sockaddr_in sin_addr; sin_addr.sin_family = AF_INET; sin_addr.sin_port = htons ( port ); sin_addr.sin_addr.s_addr = GetLocalIP(); //htonl ( INADDR_ANY ); if ( ( nSock = socket ( AF_INET, SOCK_RAW, IPPROTO_SCTP ) ) < 0 ) { perror ( "Get SCTP socket error " ); return -1; } setsockopt ( nSock, SOL_SOCKET, SO_REUSEADDR, &nOn, sizeof ( nOn ) ); ioctl ( nSock, FIONBIO, &cmdarg ); return ( nSock ); } extern void NcSetPort ( u32 port ) { tNC.nPort = port; } extern void NcSetIP ( u32 ip ) { tNC.nDstIp = ip; } extern int NcInit ( ) { memset ( &tNC, 0, sizeof ( NetCap ) ); tNC.nPort = 8000; tNC.nDstIp = inet_addr ( "172.54.240.3" ); return 1; } extern int NcStart ( u32 wIP, u32 wPort ) { if ( tNC.uState ) return 0; tNC.nDstIp = wIP ? wIP : tNC.nDstIp; tNC.nPort = wPort ? wPort : tNC.nPort; tNC.nSock = NcGetSocket ( tNC.nPort ); tNC.uState = 1; return 1; } extern int NcStop ( ) { shutdown ( tNC.nSock, 2 ); tNC.uState = 0; return 1; } #define SCTP_HEADER_LEN 0x1C #define SCCTP_CS_POS 0x08 #define SCTP_CHUNKLEN_POS 15 static u8 SCTP_HEADER[] = { 0x13, 0x56, 0x13, 0x56, 0x00, 0x00, 0x2d, 0xd1, 0x05, 0x67, 0x59, 0x7a, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x11, 0x00, 0x11, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02 }; static int NcStuffSCTP ( u8 * pIPBuff ) { memcpy ( pIPBuff, SCTP_HEADER, SCTP_HEADER_LEN ); pIPBuff[0] = 4950 >> 8; pIPBuff[1] = 4950 & 0xFF; pIPBuff[2] = tNC.nPort >> 8; pIPBuff[3] = tNC.nPort & 0xFF; return SCTP_HEADER_LEN; } #define M2UA_HEADER_LEN 0x14 #define M2UA_MSGLEN_POS 0x07 #define M2UA_PARALEN_POS 0x13 static inline int NcGetM2uaParaLen ( u32 wMtp3Len ) { return ( wMtp3Len + 4 ); } static inline int NcGetM2uaMsgLen ( u32 wMtp3Len ) { return ( NcGetM2uaParaLen ( wMtp3Len ) + 16 ); } static u8 M2UA_HEADER[] = { 0x01, 0x00, 0x06, 0x01, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x1c }; int NcStuffM2UA ( u8 * pIPBuff, u32 wMtp3Len ) { memcpy ( pIPBuff, M2UA_HEADER, M2UA_HEADER_LEN ); *( pIPBuff + M2UA_PARALEN_POS ) = NcGetM2uaParaLen ( wMtp3Len ); *( pIPBuff + M2UA_MSGLEN_POS ) = NcGetM2uaMsgLen ( wMtp3Len ); return M2UA_HEADER_LEN; } #define MTP3_HAEDER_ANSI_LEN 0x08 static u8 MTP3_HEADER_ANSI[] = { 0x83, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00 }; #define MTP3_HAEDER_ITU_LEN 0x05 static u8 MTP3_HEADER_ITU[] = { 0x83, 0x20, 0x00, 0x08, 0x00 }; static int NcStuffMtp3 ( u8 * pIPBuff, u32 wDPC, u32 wOPC, u8 uSLS, u8 uAnsiFlag ) { u32 MTP3_HAEDER_LEN; u8 *MTP3_HEADER; //printf ( "stuff mtp3 : dpc :%ld opc :%ld sls: %d , ansi :%d \n", wDPC, wOPC, // uSLS, uAnsiFlag ); if ( uAnsiFlag ) { MTP3_HEADER_ANSI[1] = wDPC ? MTP3_HEADER_ANSI[1] : wDPC; MTP3_HEADER_ANSI[4] = wOPC ? MTP3_HEADER_ANSI[4] : wOPC; MTP3_HEADER_ANSI[7] = uSLS ? MTP3_HEADER_ANSI[7] : uSLS; } else { if ( wDPC ) { MTP3_HEADER_ITU[1] = wDPC & 0xFF; MTP3_HEADER_ITU[2] &= 0xC0; MTP3_HEADER_ITU[2] |= ( wDPC >> 8 ) & 0x3F; } if ( wOPC ) { MTP3_HEADER_ITU[2] &= 0x3F; MTP3_HEADER_ITU[2] |= ( wDPC & 0x03 ) << 6; MTP3_HEADER_ITU[3] = wDPC >> 2; MTP3_HEADER_ITU[4] &= 0xF0; MTP3_HEADER_ITU[4] |= wOPC >> 10; } MTP3_HEADER_ITU[4] &= 0x0F; MTP3_HEADER_ITU[4] |= uSLS << 4; } MTP3_HEADER = uAnsiFlag ? MTP3_HEADER_ANSI : MTP3_HEADER_ITU; MTP3_HAEDER_LEN = uAnsiFlag ? MTP3_HAEDER_ANSI_LEN : MTP3_HAEDER_ITU_LEN; memcpy ( pIPBuff, MTP3_HEADER, MTP3_HAEDER_LEN ); return MTP3_HAEDER_LEN; } extern void NcMtp3Send ( u8 * pMtp3Msg, u32 wMtp3Len, u8 uAnsiFlag ) { u8 IPBuff[512]; u32 wPackLen = 0; u32 wM2uaLen = 0; u32 ad = 0; u32 MTP3_HAEDER_LEN; u8 uPad = 0; struct sockaddr_in sin_addr; memset ( IPBuff, 0, 512 * sizeof ( u8 ) ); wPackLen += NcStuffSCTP ( IPBuff + wPackLen ); MTP3_HAEDER_LEN = uAnsiFlag ? MTP3_HAEDER_ANSI_LEN : MTP3_HAEDER_ITU_LEN; wM2uaLen = NcStuffM2UA ( IPBuff + wPackLen, wMtp3Len ); wPackLen += wM2uaLen; memcpy ( IPBuff + wPackLen, pMtp3Msg, wMtp3Len ); wPackLen += wMtp3Len; uPad = ( IPBuff[SCTP_HEADER_LEN + 7] ) % 4; uPad = uPad ? ( 4 - uPad ) : 0; for ( ; uPad > 0; uPad-- ) { IPBuff[SCTP_HEADER_LEN + 7]++; //m2ua msg len IPBuff[wPackLen++] = 0x00; } IPBuff[SCTP_CHUNKLEN_POS] = 0x10 + IPBuff[SCTP_HEADER_LEN + 7]; ad = NcCS ( IPBuff, wPackLen ); IPBuff[SCCTP_CS_POS] = ad & 0xFF; IPBuff[SCCTP_CS_POS + 1] = ad / ( 256 ); IPBuff[SCCTP_CS_POS + 2] = ad / ( 256 * 256 ); IPBuff[SCCTP_CS_POS + 3] = ad / ( 256 * 256 * 256 ); sin_addr.sin_family = AF_INET; sin_addr.sin_port = htons ( tNC.nPort ); sin_addr.sin_addr.s_addr = tNC.nDstIp; sendto ( tNC.nSock, ( char * ) IPBuff, wPackLen, 0, ( struct sockaddr * ) &sin_addr, sizeof ( struct sockaddr ) ); //printf ( "\nMTP3 Send Net cap message!\n " ); } typedef struct WXC_NETCAP_SCCP_INTRA_MESSAGE { u8 msgsource; u8 msgtype; u8 msgclass; u8 msgMNP; int OPC; int DPC; u8 SLS; } Wxc_NCSccpIntra; extern int NcSccpSend ( u8 * pSccpMsg, u32 wSccpLen, u8 * pIntraMsg, BYTE uAnsiFlag ) { u8 IPBuff[512]; u32 wPackLen = 0; u32 wM2uaLen = 0; u32 ad = 0; u8 uPad = 0; u32 MTP3_HAEDER_LEN; struct sockaddr_in sin_addr; Wxc_NCSccpIntra *pIntra = ( Wxc_NCSccpIntra * ) pIntraMsg; memset ( IPBuff, 0, 512 * sizeof ( u8 ) ); wPackLen += NcStuffSCTP ( IPBuff + wPackLen ); MTP3_HAEDER_LEN = uAnsiFlag ? MTP3_HAEDER_ANSI_LEN : MTP3_HAEDER_ITU_LEN; wM2uaLen = NcStuffM2UA ( IPBuff + wPackLen, wSccpLen + MTP3_HAEDER_LEN ); wPackLen += wM2uaLen; wPackLen += NcStuffMtp3 ( IPBuff + wPackLen, pIntra->DPC, pIntra->DPC, pIntra->SLS, uAnsiFlag ); memcpy ( IPBuff + wPackLen, pSccpMsg, wSccpLen ); wPackLen += wSccpLen; uPad = ( IPBuff[SCTP_HEADER_LEN + 7] ) % 4; uPad = uPad ? ( 4 - uPad ) : 0; for ( ; uPad > 0; uPad-- ) { IPBuff[SCTP_HEADER_LEN + 7]++; //m2ua msg len IPBuff[wPackLen++] = 0x00; } IPBuff[SCTP_CHUNKLEN_POS] = 0x10 + IPBuff[SCTP_HEADER_LEN + 7]; ad = NcCS ( IPBuff, wPackLen ); IPBuff[SCCTP_CS_POS] = ad & 0xFF; IPBuff[SCCTP_CS_POS + 1] = ad / ( 256 ); IPBuff[SCCTP_CS_POS + 2] = ad / ( 256 * 256 ); IPBuff[SCCTP_CS_POS + 3] = ad / ( 256 * 256 * 256 ); sin_addr.sin_family = AF_INET; sin_addr.sin_port = htons ( tNC.nPort ); sin_addr.sin_addr.s_addr = tNC.nDstIp; if ( sendto ( tNC.nSock, ( char * ) IPBuff, wPackLen, 0, ( struct sockaddr * ) &sin_addr, sizeof ( struct sockaddr ) ) < 0 ) { perror ( "SCCP send tNC error!\n" ); return 0; } //printf ( "\nSCCP Send Net cap message!\n " ); //write(nSock, IPBuff, wPackLen); return 1; } /* #define SCCP_RLSE_LEN 0x0a static u8 SCCP_RLSD[ ] = { 0x04, 0x01, 0x04, 0x00, 0x00, 0x00, 0x74, 0x00, 0x01, 0x00 }; void main() { int i; NcInit(); NcStart(inet_addr("10.167.144.35") , 8000 ); for( i = 0 ; i < 5000 ; i ++ ) { sleep(1); NcSccpSend( SCCP_RLSD , SCCP_RLSE_LEN ); } NcStop(); return ; } */ /*@end@*/