www.pudn.com > zhuabao.rar > PacketReplayDoc.cpp
// PacketReplayDoc.cpp : implementation of the CPacketReplayDoc class
//
#include "stdafx.h"
#include "PacketReplay.h"
#include "PacketReplayDoc.h"
#include "PacketReplayView.h"//
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CPacketReplayDoc
IMPLEMENT_DYNCREATE(CPacketReplayDoc, CDocument)
BEGIN_MESSAGE_MAP(CPacketReplayDoc, CDocument)
//{{AFX_MSG_MAP(CPacketReplayDoc)
ON_COMMAND(ID_SET, OnSet)
ON_COMMAND(ID_REPLAY, OnReplay)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CPacketReplayDoc construction/destruction
extern int mAllProto;
extern int mAllDestIP;
extern int mAllSourIP;
extern int mAllSourPort;
extern int mAllDestPort;
extern int mDestPort;
extern int mSourPort;
extern CString m_strDIP;
extern CString m_strSIP;
CPacketReplayDoc::CPacketReplayDoc()
{
// TODO: add one-time construction code here
psend=new CSend();
m_data.RemoveAll();
alldevs=NULL;
d=NULL;
adhandle=NULL;
m_nDeviceCount=0;
m_nPacketNum=0;
m_ThreadHandle=NULL;
}
CPacketReplayDoc::~CPacketReplayDoc()
{
}
BOOL CPacketReplayDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
// TODO: add reinitialization code here
// (SDI documents will reuse this document)
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CPacketReplayDoc serialization
void CPacketReplayDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// TODO: add storing code here
}
else
{
// TODO: add loading code here
}
}
/////////////////////////////////////////////////////////////////////////////
// CPacketReplayDoc diagnostics
#ifdef _DEBUG
void CPacketReplayDoc::AssertValid() const
{
CDocument::AssertValid();
}
void CPacketReplayDoc::Dump(CDumpContext& dc) const
{
CDocument::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CPacketReplayDoc commands
//获取设备列表,统计网卡个数
int CPacketReplayDoc::InitPacp()
{
//获取设备列表
if(pcap_findalldevs(&alldevs,errbuf)==-1)
return -1;
for(d=alldevs;d;d=d->next)
{
m_nDeviceCount++;
}
return 1;
}
//在这个线程里捕获数据
DWORD WINAPI MyCaptureThread(LPVOID lpParameter)
{
CPacketReplayDoc* pthis=(CPacketReplayDoc*)lpParameter;
if(pthis->adhandle==NULL)
{
MessageBox(NULL,"线程中adhandle句柄错误!","提示",MB_OK);
return -1;
}
int res;
//用全局变量
struct pcap_pkthdr *header;
const u_char *pkt_data; //指向常量的指针
while((res=pcap_next_ex(pthis->adhandle,&header,&pkt_data))>=0)
{
if(res==0)
{
//time out
continue;
}
else
{
//处理捕获的数据包
int a=pthis->SavePacket(header,pkt_data); //保存数据
//通知View更新列表控件 先获得视图的指针
if(a==1)
{
POSITION curTemplatePos=pthis->GetFirstViewPosition();
CPacketReplayView* pView=(CPacketReplayView*)(pthis->GetNextView(curTemplatePos));
pView->UpdateList();//通知视图更新列表
}
}
// if(pthis->dumpfile!=NULL)
// {
// pcap_dump((unsigned char*)pthis->dumpfile,header,pkt_data);
// }
}
MessageBox(NULL,"捕获线程结束!","提示",MB_OK);
return 1;
}
//开始捕获数据包 index表示网卡的编号
int CPacketReplayDoc::StartCapture(int index)
{
if(InitPacp()==-1)
return -1;
d=alldevs;
for(int i=0;inext;
//跳转到需要捕获数据包的设备了
//if(d->description)
//MessageBox(NULL,d->description,"tip",MB_OK);
//打开设备
adhandle=pcap_open_live(d->name, //网络设备名
65535, //数据包的捕获部分长度
1, //混合模式 1 打开混合模式 0关闭混合模式
1000,//读超时值
errbuf);//错误信息缓存区
if(adhandle==NULL)
{
MessageBox(NULL,errbuf,"错误",MB_OK);
pcap_freealldevs(alldevs);
return -1;
}
//检查是否为以太网
if(pcap_datalink(adhandle)!=DLT_EN10MB)
{
MessageBox(NULL,"这不适合于非以太网的网络!","错误",MB_OK);
pcap_freealldevs(alldevs);
return -1;
}
//取得网络接口的子网掩码
if(d->addresses!=NULL)
{
netmask=((struct sockaddr_in*)(d->addresses->netmask))->sin_addr.S_un.S_addr;
}
else
{
netmask=0xffffff;
}
pcap_freealldevs(alldevs);
//这里应该创建一个线程来处理 捕获数据
LPDWORD ThreadID=NULL;
m_ThreadHandle=CreateThread(NULL,0,MyCaptureThread,this,0,ThreadID);
if(m_ThreadHandle==NULL)
{
int code=GetLastError();
CString str;
str.Format("创建线程错误,代码为%d.",code);
MessageBox(NULL,str,"错误",MB_OK);
return -1;
}
return 1;
}
//--------------------------------------------------------------------------------------
//分析刚捕获到的数据包
int CPacketReplayDoc::SavePacket(struct pcap_pkthdr *header,const u_char *pkt_data)
{
if(header==NULL || pkt_data==NULL)
{
return -1;
}
DataPacket* pdata=new DataPacket;
if(pdata==NULL)
{
AfxMessageBox("由于内存空间有限,无法再保存数据包!");
return -1;
}
/*
tcp_header* tt;
u_char uc[24]={255,19,0x30,0x29,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00};
tt=(tcp_header*)uc;
char str[10];
sprintf(str,"%d",tt->dport);
AfxMessageBox(str);
*/
/*
u_char uc[2]={255,19};
u_short * s=(u_short *)uc;
char str[5];
sprintf(str,"%X",*s);
AfxMessageBox(str);
*/
/*
int a,b;
CString s;
a=header->caplen;
b=header->len;
s.Format("caplen is %d,len is %d",a,b);
AfxMessageBox(s);
*/
//分析并保存数据
pdata->len=header->len;//保存长度
pdata->data = new u_char[header->len];
memcpy(pdata->data, pkt_data, header->len);
mac_header* mach;
ip_header* ih;
tcp_header* tcph;
udp_header* udph;
icmp_header* icmph;
//MAC
mach=(mac_header*)pkt_data; //mac头
for(int i=0;i<6;i++)
{
pdata->mach.sadd[i]=mach->sadd[i];
pdata->mach.dadd[i]=mach->dadd[i];
}
pdata->mach.mac_type=mach->mac_type;
//IP
ih=(ip_header*)(pkt_data+ARP_HEAD_LEN);//ip头
int iplen=(ih->ver_ihl & 0xf)*4;
pdata->iph.crc = ih->crc;
pdata->iph.daddr=ih->daddr;
pdata->iph.flags_fo=ih->flags_fo;
pdata->iph.identification=ih->identification;
pdata->iph.op_pad=ih->op_pad;
pdata->iph.proto=ih->proto;
pdata->iph.saddr=ih->saddr;
pdata->iph.tlen=ih->tlen;
pdata->iph.tos=ih->tos;
pdata->iph.ttl=ih->ttl;
pdata->iph.ver_ihl=ih->ver_ihl;
//TCP 或 UDP
tcp_header* ptemp=NULL;
udp_header* pudptemp=NULL;
icmp_header* icmptemp=NULL;
switch(ih->proto)
{
case TCP_PROTO: //如果是TCP
tcph=(tcp_header*)((u_char*)ih + iplen);
ptemp=new tcp_header;
ptemp->an=tcph->an;
ptemp->check_sum=tcph->check_sum;
ptemp->dport=tcph->dport;
ptemp->option=tcph->option;
ptemp->other=tcph->other;
ptemp->sn=tcph->sn;
ptemp->sport=tcph->sport;
ptemp->urgent_pointer=tcph->urgent_pointer;
ptemp->window_size=tcph->window_size;
pdata->pTCP_UDP =ptemp;
strcpy(pdata->strPacketType,"TCP");
break;
case UDP_PROTO://如果是UDP
udph=(udp_header*)((u_char*)ih + iplen);
pudptemp=new udp_header;
pudptemp->crc=udph->crc;
pudptemp->dport=udph->dport;
pudptemp->len=udph->len;
pudptemp->sport=udph->sport;
pdata->pTCP_UDP=pudptemp;
strcpy(pdata->strPacketType,"UDP");
break;
case ICMP_PROTO://如果是ICMP
icmph=(icmp_header*)((u_char*)ih + iplen);
icmptemp = new icmp_header;
icmptemp->chksum=icmph->chksum;
icmptemp->identifer=icmph->identifer;
icmptemp->sequence=icmph->sequence;
icmptemp->type=icmph->type;
pdata->pTCP_UDP=icmptemp;
strcpy(pdata->strPacketType,"ICMP");
break;
default:
pdata->pTCP_UDP=NULL;
strcpy(pdata->strPacketType,"Other");
break;
}
int proto=0,Sip=0,Dip=0,Sport=0,Dport=0;
CString str;
//过滤协议类型
if(mAllProto==0) proto=1;
else if(mAllProto==1&&strcmp(pdata->strPacketType,"TCP")==0) proto=1;
else if(mAllProto==2&&strcmp(pdata->strPacketType,"UDP")==0) proto=1;
else if(mAllProto==3&&strcmp(pdata->strPacketType,"ICMP")==0) proto=1;
else if(mAllProto==4&&strcmp(pdata->strPacketType,"Other")==0) proto=1;
else proto=0;
//过滤源IP
str.Format("%d.%d.%d.%d",pdata->iph.saddr.byte1,pdata->iph.saddr.byte2,pdata->iph.saddr.byte3,pdata->iph.saddr.byte4);
if(mAllSourIP==0) Sip=1;
else if(strcmp(str,m_strSIP)==0) Sip=1;
else Sip=0;
//过滤目的IP
str.Format("%d.%d.%d.%d",pdata->iph.daddr.byte1,pdata->iph.daddr.byte2,pdata->iph.daddr.byte3,pdata->iph.daddr.byte4);
if(mAllDestIP==0) Dip=1;
else if(strcmp(str,m_strDIP)==0) Dip=1;
else Dip=0;
//-----------------------------------------------------------------------
u_short sport,dport;
CString strSP,strDP;
if(strcmp(pdata->strPacketType,"TCP")==0)
{
tcp_header* tcph=(tcp_header*)(pdata->pTCP_UDP);
sport=ntohs(tcph->sport);
dport=ntohs(tcph->dport);
strSP.Format("%d",sport);
strDP.Format("%d",dport);
}
else if(strcmp(pdata->strPacketType,"UDP")==0)
{
udp_header* duph=(udp_header*)(pdata->pTCP_UDP);
sport=ntohs(duph->sport);
dport=ntohs(duph->dport);
strSP.Format("%d",sport);
strDP.Format("%d",dport);
}
else
{
strSP.Format("-");
strDP.Format("-");
}
//过滤源端口
if(mAllSourPort==0)Sport=1;
else
{
str.Format("%d",mSourPort);
if(strcmp(strSP,str)==0)Sport=1;
else Sport=0;
}
//过滤目的端口
if(mAllDestPort==0)Dport=1;
else
{
str.Format("%d",mDestPort);
if(strcmp(strDP,str)==0)Dport=1;
else Dport=0;
}
if(proto==1&&Sip==1&&Dip==1&&Sport==1&&Dport==1)
{
m_data.AddTail(pdata); //保存数据
return 1;;
}
else
{
delete pdata;
return -1;
}
}
//-------------------------------------------------------------------------------------
//作为框架和视图类的中介,对树的真正更新在视图类中完成
void CPacketReplayDoc::UpdateTree(int index)
{
//获得视图的指针
POSITION curTemplatePos=this->GetFirstViewPosition();
CPacketReplayView* pView=(CPacketReplayView*)(this->GetNextView(curTemplatePos));
//通知视图更新树
pView->UpdateTree(m_nPacketNum-index-1);
}
void CPacketReplayDoc::UpdateEdit(int index)
{
//获得视图的指针
POSITION curTemplatePos=this->GetFirstViewPosition();
CPacketReplayView* pView=(CPacketReplayView*)(this->GetNextView(curTemplatePos));
//通知视图更新编辑控件
pView->UpdateEdit(m_nPacketNum-index-1);
}
//分析已经保存的数据 目的是在列表中显示
int CPacketReplayDoc::AnalyzeData(DataPacket *pdata)
{
if(pdata==NULL)
{
AfxMessageBox("无效的数据指针!");
return -1;
}
//数据
u_char* buf=pdata->data;
int datalen=pdata->len;
/*
int iphead=(pdata->iph.ver_ihl&0xf) * 4;
buf=buf+ARP_HEAD_LEN+iphead;
datalen=datalen-ARP_HEAD_LEN-iphead;
*/
//序号
//itoa(m_nPacketNum,m_strIndex,10);
sprintf(m_strIndex,"%.4d",m_nPacketNum);
//总长度
//itoa(ntohs(pdata->iph.tlen),m_strSize,10);
//sprintf(m_strSize,"%X",ntohs(pdata->iph.tlen));
//IP头长
sprintf(m_strIPLen,"%d",(pdata->iph.ver_ihl & 0xf)*4);
//标识
sprintf(m_strID,"%X",ntohs(pdata->iph.identification));
//TTL
//sprintf(m_strTTL,"%X",(pdata->iph.ttl));
//类型
strcpy(m_strProto,pdata->strPacketType);
//源IP和目的IP
sprintf(m_strSourIP,"%d.%d.%d.%d",pdata->iph.saddr.byte1,pdata->iph.saddr.byte2,pdata->iph.saddr.byte3,pdata->iph.saddr.byte4);
sprintf(m_strDestIP,"%d.%d.%d.%d",pdata->iph.daddr.byte1,pdata->iph.daddr.byte2,pdata->iph.daddr.byte3,pdata->iph.daddr.byte4);
//源端口和目的端口
u_short sport,dport;
if(strcmp(pdata->strPacketType,"TCP")==0)
{
tcp_header* tcph=(tcp_header*)(pdata->pTCP_UDP);
sport=ntohs(tcph->sport);
dport=ntohs(tcph->dport);
sprintf(m_strSourPort,"%d",sport);
sprintf(m_strDestPort,"%d",dport);
}
else if(strcmp(pdata->strPacketType,"UDP")==0)
{
udp_header* duph=(udp_header*)(pdata->pTCP_UDP);
sport=ntohs(duph->sport);
dport=ntohs(duph->dport);
sprintf(m_strSourPort,"%d",sport);
sprintf(m_strDestPort,"%d",dport);
}
else
{
sprintf(m_strSourPort,"-");
sprintf(m_strDestPort,"-");
}
//TCP解析
if(strcmp(pdata->strPacketType,"TCP")==0)
{
tcp_header* ptcp=(tcp_header*)(pdata->pTCP_UDP);
//序列号
sprintf(m_strSN,"%X",ntohl(ptcp->sn));
//确认号
sprintf(m_strAN,"%X",ntohl(ptcp->an));
//窗口大小
//sprintf(m_strWindow,"%X",ntohs(ptcp->window_size));
//紧急指针
//sprintf(m_strUrgPoint,"%X",ntohs(ptcp->urgent_pointer));
//数据偏移
u_short others=ntohs(ptcp->other);
sprintf(m_strDataOff,"%d",((others & 0xf000)>>12)*4);
//sprintf(m_strFIN,"%X",(others & 0x0001));
//sprintf(m_strSYN,"%X",(others & 0x0002)>>1);
//sprintf(m_strRST,"%X",(others & 0x0004)>>2);
//sprintf(m_strPSH,"%X",(others & 0x0008)>>3);
//sprintf(m_strACK,"%X",(others & 0x0010)>>4);
//sprintf(m_strURG,"%X",(others & 0x0020)>>5);
/*
int tcphead=((others & 0xf000)>>12)*4;
buf+=tcphead;
datalen-=tcphead;
*/
}
else
{
sprintf(m_strDataOff,"-");
sprintf(m_strSN,"-");
sprintf(m_strAN,"-");
//sprintf(m_strWindow,"-");
//sprintf(m_strUrgPoint,"-");
//sprintf(m_strFIN,"-");
//sprintf(m_strSYN,"-");
//sprintf(m_strRST,"-");
//sprintf(m_strPSH,"-");
//sprintf(m_strACK,"-");
//sprintf(m_strURG,"-");
/*
if(strcmp(pdata->strPacketType,"UDP")==0)
{
buf+=UDP_HEAD_LEN;
datalen-=UDP_HEAD_LEN;
}
else if(strcmp(pdata->strPacketType,"ICMP")==0)
{
buf+=ICMP_HEAD_LEN;
datalen-=ICMP_HEAD_LEN;
}
else
{
}
*/
}
CString str,str2;
for(int i=0;ipTCP_UDP;
delete p;
}
m_data.RemoveAll();
}
m_nPacketNum=0;
}
//------------------------------------------------------------------------------
void CPacketReplayDoc::OnSet()
{
// TODO: Add your command handler code here
set.DoModal();
}
void CPacketReplayDoc::OnReplay()
{
//TODO: Add your command handler code here
if(psend->GetSafeHwnd()==0)
psend->Create(CSend::IDD);
else psend->SetFocus();
}