📄 tcpparser.c
字号:
#include <linux/module.h>
#include <linux/config.h>
#include <linux/init.h>
#include <linux/netdevice.h> /* for dev_base */
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/file.h>
#include <linux/dnotify.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/time.h>
#include <linux/rcupdate.h>
#include <asm/semaphore.h>
#include <asm/unistd.h>
#include <asm/atomic.h>
#include "createDir.h"
#include "DomainIPHash.h"
#include "Rule.h"
#include "RuleIp.h"
#include "list.h"
#include "protocol.h"
#include "TcpParser.h"
#include "function.h"
extern GVAR gVar;
extern TRAFFIC_STAT_INFO statInfo;
int TCPAppParser( void *arg )
{
struct iphdr *pIpHeader;
struct tcphdr *pTcpHeader;
PTHREAD_CONTROL pThreadSigual = (PTHREAD_CONTROL)arg;
UINT iRead;
char* pPacket;
PDOUBLE_LIST_PACKET pItem;
USHORT dataLen,dataOffset;
int packet_len;
daemonize( "tcp" );
allow_signal(SIGTERM);
while( !signal_pending( current ) )
{
if( ( gVar.TcpCycArrayHead.iWrite.counter - gVar.TcpCycArrayHead.iRead.counter ) < _MAX_CYC_SAFE_NUMBER )
{
if( !gVar.CtrlThreadCtx.bReady )
gVar.CtrlThreadCtx.bReady = true;
schedule();
continue;
}
iRead = atomic64_read( &gVar.TcpCycArrayHead.iRead );
atomic64_inc( &gVar.TcpCycArrayHead.iRead );
iRead = iRead % _MAX_CYC_ARRAY_DEPTH;
pPacket = gVar.TcpCycArrayHead.PacketArray[ iRead ]->buf;
pIpHeader = (struct iphdr * )pPacket;
pTcpHeader = (struct tcphdr *)( (UCHAR *)pIpHeader + pIpHeader->ihl * 4 );
packet_len = gVar.TcpCycArrayHead.PacketArray[ iRead ]->len;
dataOffset = pIpHeader->ihl * 4 + pTcpHeader->doff * 4 ;
dataLen = packet_len - dataOffset;
if( !pTcpHeader->syn && !pTcpHeader->fin && pTcpHeader->dest != HTTP_PORT_NET
&& pTcpHeader->source != HTTP_PORT_NET && dataLen == 0 )
{
continue;
}
if( ( dataOffset + dataLen ) > _MAX_PACKET_LEN || packet_len > 1520
|| ( dataOffset + dataLen ) > (USHORT)gVar.TcpCycArrayHead.PacketArray[ iRead ]->len )
{
continue;
}
if( packet_len > _SHORT_PACKET_LEN )
{
pItem = (PDOUBLE_LIST_PACKET)GetLongPacketPool();
if( pItem == NULL )
{
printk( "xxx:haven't long leisure pool\r\n" );
gVar.CtrlThreadCtx.bReady = false;
continue;
}
}
else
{
pItem = (PDOUBLE_LIST_PACKET)GetShortPacketPool();
if( pItem == NULL )
{
printk( "xxx:haven't short leisure pool\r\n" );
gVar.CtrlThreadCtx.bReady = false;
continue;
}
}
pItem->packet.len = packet_len;
pItem->packet.dataOffset = dataOffset;
pItem->packet.dataLen = dataLen;
pItem->packet.IPType = gVar.TcpCycArrayHead.PacketArray[ iRead ]->IPType;
pItem->packet.pConfig = gVar.TcpCycArrayHead.PacketArray[ iRead ]->pConfig;
pItem->packet.ruleID = gVar.TcpCycArrayHead.PacketArray[ iRead ]->ruleID;
if( pTcpHeader->syn || pTcpHeader->fin )
{
if( ( _MAX_UINT - htonl( pTcpHeader->seq ) ) == 0 )
pItem->packet.nextSeqNumber = 0;
else
pItem->packet.nextSeqNumber = htonl( pTcpHeader->seq ) + 1;
}
else
{
if( ( _MAX_UINT - htonl( pTcpHeader->seq ) ) < pItem->packet.dataLen )
pItem->packet.nextSeqNumber = pItem->packet.dataLen - ( _MAX_UINT - htonl( pTcpHeader->seq ) ) - 1;
else
pItem->packet.nextSeqNumber = htonl( pTcpHeader->seq ) + pItem->packet.dataLen;
}
memcpy( pItem->packet.buf, pPacket, packet_len );
pItem->packet.AppType = gVar.TcpCycArrayHead.PacketArray[ iRead ]->AppType;
switch( gVar.TcpCycArrayHead.PacketArray[ iRead ]->AppType )
{
case APP_TYPE_SMTP:
case APP_TYPE_POP3:
statInfo.MailTotalBytes += packet_len;
if( pTcpHeader->dest == SMTP_PORT_NET )
pItem->packet.type = PACKET_TYPE_SMTP_CLIENT;
else if( pTcpHeader->source == POP3_PORT_NET )
pItem->packet.type = PACKET_TYPE_POP3_SERVER;
else if( pTcpHeader->dest == POP3_PORT_NET )
pItem->packet.type = PACKET_TYPE_POP3_CLIENT;
_InsertHeadList( gVar.pSmtpQueque, &pItem->doubleListItem );
break;
case APP_TYPE_HTTP_MAIL:
if( pTcpHeader->dest == HTTP_PORT_NET )
pItem->packet.type = PACKET_TYPE_CLIENT;
else
pItem->packet.type = PACKET_TYPE_SERVER;
_InsertHeadList( gVar.pHttpQueque, &pItem->doubleListItem );
break;
case APP_TYPE_MSN:
if( pTcpHeader->dest == MSN_PORT_NET )
pItem->packet.type = PACKET_TYPE_CLIENT;
else
pItem->packet.type = PACKET_TYPE_SERVER;
_InsertHeadList( gVar.pMsnQueque, &pItem->doubleListItem );
break;
case APP_TYPE_HTTP_URL:
_InsertHeadList( gVar.pHttpUrlQueque, &pItem->doubleListItem );
break;
case APP_TYPE_HTTP_POST:
if( ParserPostPacket( pItem ) )
{
//与HTTP_URL用同一个队列
_InsertHeadList( gVar.pHttpUrlQueque, &pItem->doubleListItem );
}
else
{
//不是POST数据包,直接释放内存
PutPacketPool( pItem );
}
//采集单个POST数据包
if( HTTP_POST == GetHttpDataType( pItem ) )
{
//与HTTP_URL用同一个队列
_InsertHeadList( gVar.pHttpUrlQueque, &pItem->doubleListItem );
}
else
{
//不是POST数据包,直接释放内存
PutPacketPool( pItem );
}
break;
case APP_TYPE_FTP:
if( pTcpHeader->dest == FTP_PORT_NET )
pItem->packet.type = PACKET_TYPE_CLIENT;
else
pItem->packet.type = PACKET_TYPE_SERVER;
_InsertHeadList( gVar.pFtpQueque, &pItem->doubleListItem );
break;
case APP_TYPE_TELNET:
if( pTcpHeader->dest == TELNET_PORT_NET )
pItem->packet.type = PACKET_TYPE_CLIENT;
else
pItem->packet.type = PACKET_TYPE_SERVER;
_InsertHeadList( gVar.pTelnetQueque, &pItem->doubleListItem );
break;
case APP_TYPE_ICQ:
if( pTcpHeader->dest == ICQ_PORT_NET )
pItem->packet.type = PACKET_TYPE_CLIENT;
else
pItem->packet.type = PACKET_TYPE_SERVER;
_InsertHeadList( gVar.pIcqQueque, &pItem->doubleListItem );
break;
case APP_TYPE_YAHOOMSG:
if( pTcpHeader->dest == YAHOO_PORT_NET
|| pTcpHeader->dest == YAHOO_PORT_NET_119
|| pTcpHeader->dest == YAHOO_PORT_NET_5101)
{
pItem->packet.type = PACKET_TYPE_CLIENT;
}
else
pItem->packet.type = PACKET_TYPE_SERVER;
_InsertHeadList( gVar.pYahooQueque, &pItem->doubleListItem );
break;
case APP_TYPE_IRC:
if( pTcpHeader->dest == IRC_PORT_NET )
pItem->packet.type = PACKET_TYPE_CLIENT;
else
pItem->packet.type = PACKET_TYPE_SERVER;
_InsertHeadList( gVar.pIrcQueque, &pItem->doubleListItem );
break;
case APP_TYPE_PP:
if( pTcpHeader->dest == PP_PORT_NET )
pItem->packet.type = PACKET_TYPE_CLIENT;
else
pItem->packet.type = PACKET_TYPE_SERVER;
_InsertHeadList( gVar.pPpQueque, &pItem->doubleListItem );
break;
case APP_TYPE_GTALK:
if( pTcpHeader->dest == GTALK_PORT_NET )
pItem->packet.type = PACKET_TYPE_CLIENT;
else
pItem->packet.type = PACKET_TYPE_SERVER;
_InsertHeadList( gVar.pGtalkQueque, &pItem->doubleListItem );
break;
default:
PutPacketPool( pItem );
break;
}
schedule();
}
complete_and_exit( &(pThreadSigual->thread_exited), 1 );
return 0;
}
UINT GetProtocolType( UCHAR* pPacket )
{
struct iphdr *pIPHeader; // See ip.h
struct tcphdr *pTCPHeader; // See tcp.h
pIPHeader = (struct iphdr * )pPacket;
pTCPHeader = (struct tcphdr *)( (UCHAR *)pIPHeader + pIPHeader->ihl );
printk("the ip head len:%d\r\n", pIPHeader->ihl );
if( ntohs((pTCPHeader->source)) == SMTP_PORT
|| ntohs(pTCPHeader->dest) == SMTP_PORT )
{
return TCP_P_SMTP;
}
if( ntohs(pTCPHeader->source) == POP3_PORT
|| ntohs(pTCPHeader->dest) == POP3_PORT )
{
return TCP_P_POP3;
}
return TCP_P_UNKNOWN;
}
//
//判断采集到HTTP数据类型
//
UINT GetHttpDataType( PDOUBLE_LIST_PACKET pItem )
{
char *pHttp = NULL;
if( pItem->packet.dataLen < 5
|| pItem->packet.dataLen > HTTP_POST_LEN_LIMINTED_LEN )
{
return HTTP_OTHER;
}
pHttp = (char *)( pItem->packet.buf + pItem->packet.dataOffset );
switch( (*(UINT *)pHttp) )
{
//' TEG'
case 0x20544547:
return HTTP_GET;
//'TSOP'
case 0x54534F50:
return HTTP_POST;
default:
return HTTP_OTHER;
}
}
char ParserPostPacket(PDOUBLE_LIST_PACKET pItem)
{
// struct ethhdr *pEthHdr; // See ethernet.h
struct iphdr *pIPHeader; // See ip.h
struct tcphdr *pTCPHeader; // See tcp.h
// PSMTP_HASH_HEAD pHashHead;
char bReturn = false;
UINT uiHash;
// UINT len = 0;
UINT dataType;
if( pItem->packet.dataLen <= 5 )
return bReturn;
dataType = GetHttpDataType( pItem);
switch( dataType )
{
case HTTP_GET:
return bReturn;
default:
break;
}
pIPHeader = (struct iphdr *)pItem->packet.buf;
pTCPHeader = (struct tcphdr *)( (UCHAR *)pIPHeader + pIPHeader->ihl * 4 );
uiHash = pTCPHeader->ack_seq % _MAX_HTTP_POST_BUCKET;
if( dataType == HTTP_OTHER && gVar.pPostHash[uiHash]->pHead == NULL )
return bReturn;
bReturn = HandlePostPacket(gVar.pPostHash[uiHash], pItem, dataType);
return( bReturn);
}
char HandlePostPacket( PDOUBLE_LIST_HEAD pPostHashBucket ,
PDOUBLE_LIST_PACKET pItem, UINT dataType )
{
struct iphdr *pIPHeader; // See ip.h
struct tcphdr *pTCPHeader; // See tcp.h
UINT zero;
PSMTP_HASH_HEAD pPostHashHead;
DOUBLE_LIST_HEAD OutPut;
_InitializeList( &OutPut );
pIPHeader = (struct iphdr *)(pItem->packet.buf + ETHER_HDR_LEN );
pTCPHeader = (struct tcphdr *)( (UCHAR *)pIPHeader + (pIPHeader->ihl)*4 );
zero = 0;
down_interruptible( &pPostHashBucket->fastMutex );
pPostHashHead = (PSMTP_HASH_HEAD)pPostHashBucket->pHead;
switch( dataType )
{
case HTTP_POST:
//直接创建新的HASH头
pPostHashHead = ALLOCATE_HASHHEAD( GFP_ATOMIC, sizeof(SMTP_HASH_HEAD));
if( pPostHashHead == NULL )
{
printk("Allocate pMsnHashHead fail\r\n");
up( &pPostHashBucket->fastMutex );
return false;
}
InitializeSmtpHashHead( pPostHashHead );
pPostHashHead->sIP = pIPHeader->saddr;
pPostHashHead->cAck = pTCPHeader->ack_seq;
pPostHashHead->sPort = pTCPHeader->source;
do_gettimeofday( &pPostHashHead->timeStamp );
pItem->timeStamp = pPostHashHead->timeStamp;
pPostHashHead->ruleID = pItem->packet.ruleID;
_InsertHeadListNonLock( pPostHashBucket, &pPostHashHead->item );
break;
case HTTP_OTHER:
//查找HASH头,没有者返回false
while( pPostHashHead )
{
if( pTCPHeader->source == pPostHashHead->sPort
&& pIPHeader->saddr == pPostHashHead->sIP
&& pTCPHeader->ack_seq == pPostHashHead->cAck )
break;
pPostHashHead = (PSMTP_HASH_HEAD)pPostHashHead->item.pNext;
}
if( pPostHashHead == NULL )
{
up( &pPostHashBucket->fastMutex );
return false;
}
pItem->timeStamp = pPostHashHead->timeStamp;
break;
}
up( &pPostHashBucket->fastMutex );
return true;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -