⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcpparser.c

📁 Linux下面截获以态网数据包!是在内核态下面运行的驱动程序
💻 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 + -