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

371 lines
8.7 KiB
C

//////////////////////////////////////////////////
//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@*/