www.pudn.com > zhuabao.rar > PacketReplayView.cpp
// PacketReplayView.cpp : implementation of the CPacketReplayView 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
/////////////////////////////////////////////////////////////////////////////
// CPacketReplayView
IMPLEMENT_DYNCREATE(CPacketReplayView, CView)
BEGIN_MESSAGE_MAP(CPacketReplayView, CView)
//{{AFX_MSG_MAP(CPacketReplayView)
ON_COMMAND(ID_START, OnStart)
ON_COMMAND(ID_STOP, OnStop)
ON_UPDATE_COMMAND_UI(ID_START, OnUpdateStart)
ON_UPDATE_COMMAND_UI(ID_STOP, OnUpdateStop)
ON_COMMAND(ID_FILE_NEW, OnFileNew)
ON_COMMAND(ID_FILE_SAVE, OnFileSave)
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CPacketReplayView construction/destruction
CPacketReplayView::CPacketReplayView()
{
// TODO: add construction code here
m_pFrame=NULL;
m_pEdit=NULL;
m_pTree=NULL;
m_pList=NULL;
m_pComboBox=NULL;
m_nTotalPacket=0;
m_nTCPPacket=0;
m_nUDPPacket=0;
m_nICMPPacket=0;
m_nOtherPacket=0;
m_bEnableStart=true;//开始按钮有效
m_bEnableStop=false; //停止按钮无效
}
CPacketReplayView::~CPacketReplayView()
{
}
BOOL CPacketReplayView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CPacketReplayView drawing
void CPacketReplayView::OnDraw(CDC* pDC)
{
CPacketReplayDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
}
/////////////////////////////////////////////////////////////////////////////
// CPacketReplayView printing
BOOL CPacketReplayView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
void CPacketReplayView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CPacketReplayView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}
/////////////////////////////////////////////////////////////////////////////
// CPacketReplayView diagnostics
#ifdef _DEBUG
void CPacketReplayView::AssertValid() const
{
CView::AssertValid();
}
void CPacketReplayView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CPacketReplayDoc* CPacketReplayView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CPacketReplayDoc)));
return (CPacketReplayDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CPacketReplayView message handlers
void CPacketReplayView::OnStart()
{
// TODO: Add your command handler code here
m_pFrame=(CMainFrame*)AfxGetApp()->m_pMainWnd;
m_pEdit=m_pFrame->GetEdit(); //获取编辑框的指针
m_pList=m_pFrame->GetList(); //获取列表框的指针
m_pTree=m_pFrame->GetTree(); //获取树型控件的指针
m_pComboBox=m_pFrame->GetComboBox() ;//获取组合框的指针
int index=m_pComboBox->GetCurSel(); //获得组合框的选择
if(index==CB_ERR || index==0)
{
MessageBox("请你先选择一个网卡.");
return;
}
m_pDoc=this->GetDocument();
m_pEdit->SetWindowText("开始捕获数据.......");
m_pDoc->StartCapture(index);//开始捕获数据包 index为要捕获的网络设备的序号
m_bEnableStart=false;
m_bEnableStop=true;
}
void CPacketReplayView::OnStop()
{
// TODO: Add your command handler code here
m_pDoc=this->GetDocument();
int res=m_pDoc->StopCapture();
if(res==0)
{
MessageBox("捕获线程还没有运行!");
return;
}
else if(res==-1)
{
MessageBox("无法停止捕获线程,请稍后再试!");
return;
}
else if(res==1)
{
CString str0,str,total;
CString tcp;
CString udp;
CString icmp;
CString other;
str0.Format("==========已经停止捕获数据包!==========");
total.Format("==========总数=%d (",m_nTotalPacket);
tcp.Format("TCP=%d ",m_nTCPPacket);
udp.Format("UDP=%d ",m_nUDPPacket);
icmp.Format("ICMP=%d ",m_nICMPPacket);
other.Format("其他=%d)==========",m_nOtherPacket);
str=str0+"\r\n"+total+tcp+udp+icmp+other;
m_pEdit->SetWindowText(str);
}
m_bEnableStart=true;
m_bEnableStop=false;
}
//-------------------------------------------------------------------------------------
void CPacketReplayView::OnUpdateStart(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->Enable(m_bEnableStart);
}
void CPacketReplayView::OnUpdateStop(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->Enable(m_bEnableStop);
}
//Doc捕获到数据后,View更新列表控件
void CPacketReplayView::UpdateList()
{
if(m_pFrame==NULL)
{
m_pFrame=(CMainFrame*)AfxGetApp()->m_pMainWnd;
m_pEdit=m_pFrame->GetEdit(); //获取编辑框的指针
m_pList=m_pFrame->GetList(); //获取列表框的指针
m_pTree=m_pFrame->GetTree(); //获取树型控件的指针
}
m_pDoc=this->GetDocument();
DataPacket* pdata=(DataPacket*)(m_pDoc->m_data.GetTail()); //取得最后保存的数据
m_pDoc->AnalyzeData(pdata);
//更新列表显示
char itemname[10];
sprintf(itemname,"packet%d",m_pDoc->m_nPacketNum);
int nItem=m_pList->InsertItem(m_pDoc->m_nPacketNum++,itemname);
m_pList->SetItemText(nItem,0,m_pDoc->m_strIndex); //序号
m_pList->SetItemText(nItem,1,m_pDoc->m_strProto);//协议
m_pList->SetItemText(nItem,2,m_pDoc->m_strSourIP);//源地址
m_pList->SetItemText(nItem,3,m_pDoc->m_strSourPort);//源端口
m_pList->SetItemText(nItem,4,m_pDoc->m_strDestIP);//目的地址
m_pList->SetItemText(nItem,5,m_pDoc->m_strDestPort);//目的端口
m_pList->SetItemText(nItem,6,m_pDoc->m_strID);//标识
m_pList->SetItemText(nItem,7,m_pDoc->m_strSize);//包长度
m_pList->SetItemText(nItem,8,m_pDoc->m_strIPLen);//IP头长
m_pList->SetItemText(nItem,9,m_pDoc->m_strDataOff);//数据偏移,TCP头长
m_pList->SetItemText(nItem,10,m_pDoc->m_strSN);//序列号
m_pList->SetItemText(nItem,11,m_pDoc->m_strAN);//确认序列号
m_pList->SetItemText(nItem,12,m_pDoc->m_strData); //数据
/*
m_pList->SetItemText(nItem,8,m_pDoc->m_strTTL);//TTL
m_pList->SetItemText(nItem,12,m_pDoc->m_strURG);//URG
m_pList->SetItemText(nItem,13,m_pDoc->m_strACK);//ACK
m_pList->SetItemText(nItem,14,m_pDoc->m_strPSH);//PSH
m_pList->SetItemText(nItem,15,m_pDoc->m_strRST);//RST
m_pList->SetItemText(nItem,16,m_pDoc->m_strSYN);//RST
m_pList->SetItemText(nItem,17,m_pDoc->m_strFIN);//FIN
m_pList->SetItemText(nItem,18,m_pDoc->m_strWindow);//窗口
m_pList->SetItemText(nItem,19,m_pDoc->m_strUrgPoint); //紧急指针
*/
m_nTotalPacket++;//总量
if(strcmp(m_pDoc->m_strProto,"TCP")==0)
{
m_nTCPPacket++;
}
else if(strcmp(m_pDoc->m_strProto,"UDP")==0)
{
m_nUDPPacket++;
}
else if(strcmp(m_pDoc->m_strProto,"ICMP")==0)
{
m_nICMPPacket++;
}
else
{
m_nOtherPacket++;
}
CString str;
CString totle;
CString tcp;
CString udp;
CString icmp;
CString other;
totle.Format("总数=%d (",m_nTotalPacket);
tcp.Format("TCP=%d ",m_nTCPPacket);
udp.Format("UDP=%d ",m_nUDPPacket);
icmp.Format("ICMP=%d ",m_nICMPPacket);
other.Format("其他=%d) ",m_nOtherPacket);
str=totle+tcp+udp+icmp+other;
m_pEdit->SetWindowText(str);
}
//-------------------------------------------------------------------------------------
void CPacketReplayView::OnFileNew()
{
// TODO: Add your command handler code here
int res=MessageBox("确定要清空列表中的所有数据吗?","提示",MB_OKCANCEL);
if(res==IDOK)
{
m_pFrame=(CMainFrame*)AfxGetApp()->m_pMainWnd;
m_pList=m_pFrame->GetList();
m_pTree=m_pFrame->GetTree();
m_pList->DeleteAllItems();//清空列表
m_pTree->DeleteAllItems();
m_pDoc=this->GetDocument();
m_pDoc=this->GetDocument();
m_pDoc->CleanData(); //清空数据
}
else
{
return;
}
}
CString CPacketReplayView::MakeLen(CString str,int len)
{
if(str.GetLength()m_pMainWnd;
m_pList=m_pFrame->GetList();
int Count=m_pList->GetItemCount();
CFile f;
CFileException e;
CString strFileName;
CTime t=CTime::GetCurrentTime();
CString strTime = t.Format( "%m.%d-%H-%M-%S" );
strTime="PACKET_LOG-"+strTime;
CFileDialog fileDlg(FALSE,"log",strTime,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,"log",NULL); //TRUE 为打开对话框
if(fileDlg.DoModal()==IDOK)
{
UpdateData(true);
strFileName=fileDlg.GetFileName();
UpdateData(false);
if( f.Open(strFileName, CFile::modeCreate | CFile::modeWrite, &e ) )
{
CString str;
str="序号 协议 源地址 端口 目的地址 端口 \
标识 包长度 IP头长 TCP头长 序列号 确认序列号 数据\r\n\r\n";
f.Write( str, str.GetLength() );
str.Format("%d\r\n\r\n",Count-1);
f.Write( str, str.GetLength() );
for(int i=Count-1;i>0;i--)
{
str=MakeLen(m_pList->GetItemText(i,0),6)
+MakeLen(m_pList->GetItemText(i,1),6)
+MakeLen(m_pList->GetItemText(i,2),16)
+MakeLen(m_pList->GetItemText(i,3),8)
+MakeLen(m_pList->GetItemText(i,4),16)
+MakeLen(m_pList->GetItemText(i,5),8)
+MakeLen(m_pList->GetItemText(i,6),9)
+MakeLen(m_pList->GetItemText(i,7),9)
+MakeLen(m_pList->GetItemText(i,8),9)
+MakeLen(m_pList->GetItemText(i,9),9)
+MakeLen(m_pList->GetItemText(i,10),10)
+MakeLen(m_pList->GetItemText(i,11),12)
+MakeLen(m_pList->GetItemText(i,12),100);
str+="\r\n\r\n";
f.Write( str, str.GetLength() );
}
f.Close();
}
}
}
//------------------------------------------------------------------------------------
//在列表中选中某个数据包后,此函数负责更新树型控件的显示
void CPacketReplayView::UpdateTree(int index)
{
m_pDoc=this->GetDocument(); //获取文档指针
//从文档中获取数据
POSITION pos=m_pDoc->m_data.FindIndex(index);
DataPacket* pdata=(DataPacket*)(m_pDoc->m_data.GetAt(pos));
if(pdata==NULL)
{
MessageBox("获取数据错误!");
return;
}
m_pTree->DeleteAllItems();//先删除所有的元素
//开始分析数据并更新树
HTREEITEM root=m_pTree->GetRootItem();//获得树的根元素
HTREEITEM data=m_pTree->InsertItem(_T("接收到的数据包"),root);
//MAC
HTREEITEM mac=m_pTree->InsertItem(_T("MAC帧头"),data);
char SourMAC[28];//源MAC地址
char DestMAC[28];//目的MAC地址
char PacketType[15];
strcpy(SourMAC,"源MAC:");
strcpy(DestMAC,"目的MAC:");
for(int i=0;i<6;i++)
{
char sm[3];
if(i!=5)
{
sprintf(sm,"%X.",pdata->mach.sadd[i]);
strcat(SourMAC,sm);
sprintf(sm,"%X.",pdata->mach.dadd[i]);
strcat(DestMAC,sm);
}
else
{
sprintf(sm,"%X",pdata->mach.sadd[i]);
strcat(SourMAC,sm);
sprintf(sm,"%X",pdata->mach.dadd[i]);
strcat(DestMAC,sm);
}
}
sprintf(PacketType,"MAC类型:%X",pdata->mach.mac_type);
m_pTree->InsertItem(SourMAC,mac);
m_pTree->InsertItem(DestMAC,mac);
m_pTree->InsertItem(PacketType,mac);
//IP
HTREEITEM ip=m_pTree->InsertItem(_T("IP包头"),data);
//版本
char version[8];
sprintf(version,"版本:%X",(pdata->iph.ver_ihl & 0xf0));
m_pTree->InsertItem(version,ip);
//头长
char headlen[15];
sprintf(headlen,"IP头长:%d",(pdata->iph.ver_ihl & 0xf)*4);
m_pTree->InsertItem(headlen,ip);
//服务类型
char tos[10];
sprintf(tos,"服务类型:%X",(pdata->iph.tos));
m_pTree->InsertItem(tos,ip);
//总长度
char tln[10];
//sprintf(tln,"总长度:%X",(pdata->iph.tlen)>>8);
sprintf(tln,"总长度:%X",ntohs(pdata->iph.tlen));
m_pTree->InsertItem(tln,ip);
//标识
char identification[10];
//sprintf(identification,"标识:%X",(pdata->iph.identification)>>8);
sprintf(identification,"标识:%X",ntohs(pdata->iph.identification));
m_pTree->InsertItem(identification,ip);
//标志
char flag[10];
//u_short flags=pdata->iph.flags_fo;
//sprintf(flag,"标志:%X",(flags >> 13) & 0xe);
u_short flags=ntohs(pdata->iph.flags_fo);
sprintf(flag,"标志:%X",(flags >> 13) & 0x7);
m_pTree->InsertItem(flag,ip);
//段偏移
char offset[12];
//sprintf(offset,"段偏移:%X",(pdata->iph.flags_fo )& 0xeff);
sprintf(offset,"段偏移:%X",ntohs(pdata->iph.flags_fo )& 0x1fff);
m_pTree->InsertItem(offset,ip);
//生存期
char ttl[15];
sprintf(ttl,"生存期:%X",(pdata->iph.ttl));
m_pTree->InsertItem(ttl,ip);
//协议
char proto[10];
sprintf(proto,"协议:%X",pdata->iph.proto);
m_pTree->InsertItem(proto,ip);
//头部校验和
char checksum[20];
//sprintf(checksum,"头部校验和:%X",pdata->iph.crc);
sprintf(checksum,"头部校验和:%X",ntohs(pdata->iph.crc));
m_pTree->InsertItem(checksum,ip);
//源IP
char sourip[20];
sprintf(sourip,"源IP:%d.%d.%d.%d",
pdata->iph.saddr.byte1,
pdata->iph.saddr.byte2,
pdata->iph.saddr.byte3,
pdata->iph.saddr.byte4);
m_pTree->InsertItem(sourip,ip);
//目的IP
char destip[20];
sprintf(destip,"源IP:%d.%d.%d.%d",
pdata->iph.daddr.byte1,
pdata->iph.daddr.byte2,
pdata->iph.daddr.byte3,
pdata->iph.daddr.byte4);
m_pTree->InsertItem(destip,ip);
//TCP UDP ICMP
if(strcmp(pdata->strPacketType,"TCP")==0)
{
HTREEITEM tcp=m_pTree->InsertItem(_T("TCP头信息"),data);
tcp_header* ptcp=(tcp_header*)(pdata->pTCP_UDP);
//源端口
char sport[15];
sprintf(sport,"源端口:%X",ntohs(ptcp->sport));
m_pTree->InsertItem(sport,tcp);
//目的端口
char dport[15];
sprintf(dport,"目的端口:%X",ntohs(ptcp->dport));
m_pTree->InsertItem(dport,tcp);
//序列号
char sn[20];
sprintf(sn,"序列号:%X",ntohl(ptcp->sn));
m_pTree->InsertItem(sn,tcp);
//确认号
char an[20];
sprintf(an,"确认号:%X",ntohl(ptcp->an));
m_pTree->InsertItem(an,tcp);
//头长
char headl[20];
sprintf(headl,"头长等:%X",ntohs(ptcp->other));
m_pTree->InsertItem(headl,tcp);
//窗口大小
char winsize[20];
sprintf(winsize,"窗口大小:%X",ntohs(ptcp->window_size));
m_pTree->InsertItem(winsize,tcp);
//校验和
char cks[20];
sprintf(cks,"校验和:%X",ntohs(ptcp->check_sum));
m_pTree->InsertItem(cks,tcp);
//紧急指针
char urp[20];
sprintf(urp,"紧急指针:%X",ntohs(ptcp->urgent_pointer));
m_pTree->InsertItem(urp,tcp);
//选项
char option[10];
sprintf(option,"选项:%X",ntohl(ptcp->option));
m_pTree->InsertItem(option,tcp);
m_pTree->Expand(tcp,TVE_EXPAND);
}
else if(strcmp(pdata->strPacketType,"UDP")==0)
{
HTREEITEM udp=m_pTree->InsertItem(_T("UDP头信息"),data);
udp_header* pudp=(udp_header*)(pdata->pTCP_UDP);
//源端口
char sport[15];
sprintf(sport,"源端口:%X",ntohs(pudp->sport));
m_pTree->InsertItem(sport,udp);
//目的端口
char dport[15];
sprintf(dport,"目的端口:%X",ntohs(pudp->dport));
m_pTree->InsertItem(dport,udp);
//总长度
char tlen[15];
sprintf(tlen,"总长度:%X",ntohs(pudp->len));
m_pTree->InsertItem(tlen,udp);
//校验和
char chk[20];
sprintf(chk,"校验和:%X",ntohs(pudp->crc));
m_pTree->InsertItem(chk,udp);
m_pTree->Expand(udp,TVE_EXPAND);
}
else if(strcmp(pdata->strPacketType,"ICMP")==0)
{
HTREEITEM icmp=m_pTree->InsertItem(_T("ICMP头信息"),data);
icmp_header* picmp=(icmp_header*)(pdata->pTCP_UDP);
//类型
char type[25];
sprintf(type,"类型:%X",picmp->type);
switch(picmp->type)
{
case 0:
strcat(type,"(回应应答)");
break;
case 3:
strcat(type,"(目的不可达)");
break;
case 4:
strcat(type,"(源抑制)");
break;
case 5:
strcat(type,"(重定向)");
break;
case 8:
strcat(type,"(回应请求)");
break;
case 11:
strcat(type,"(数据包超时)");
break;
case 12:
strcat(type,"(数据包参数错误)");
break;
case 13:
strcat(type,"(时戳请求)");
break;
case 14:
strcat(type,"(时戳响应)");
break;
case 17:
strcat(type,"(地址源码请求)");
break;
case 18:
strcat(type,"(地址源码响应)");
break;
default:
strcat(type,"(尚未识别的类型)");
break;
}
m_pTree->InsertItem(type,icmp);
//代码
char daima[10];
sprintf(daima,"代码:%X",picmp->identifer);
m_pTree->InsertItem(daima,icmp);
//序号
char sn[20];
sprintf(sn,"序号:%X",picmp->sequence);
m_pTree->InsertItem(sn,icmp);
//校验和
char cs[20];
sprintf(cs,"校验和:%X",picmp->chksum);
m_pTree->InsertItem(cs,icmp);
m_pTree->Expand(icmp,TVE_EXPAND);
}
else
{
HTREEITEM other=m_pTree->InsertItem(_T("尚未分析的头信息"),data);
}
m_pTree->Expand(data,TVE_EXPAND);
m_pTree->Expand(mac,TVE_EXPAND);
m_pTree->Expand(ip,TVE_EXPAND);
}
void CPacketReplayView::UpdateEdit(int index)
{
m_pDoc=this->GetDocument(); //获取文档指针
//从文档中获取数据
POSITION pos=m_pDoc->m_data.FindIndex(index);
DataPacket* pdata=(DataPacket*)(m_pDoc->m_data.GetAt(pos));
if(pdata==NULL)
{
MessageBox("获取数据错误!");
return;
}
CString str,temp,temp2;
str.Format("Frame %.4d ",index);
str+="\r\n";
temp2="||";
int i=0;
while((ilen))
{
if((i%MAX_LINE)==0)
{
if(i>0)
{
str+=temp2;
temp2="||";
}
str+="\r\n";
temp.Format("%.4X||",i);
str+=temp;
}
temp.Format("%3.2X",(pdata->data)[i]);
str+=temp;
temp.Format("%c",(pdata->data)[i]);
if(temp>' '&&temp<'~')
temp2+=temp;
else
temp2+=".";
i++;
}
if(i%MAX_LINE)
{
while(i%MAX_LINE)
{
str+=" ";
i++;
}
str+=temp2;
}
else
str+=temp2;
m_pEdit->SetWindowText(str);
}