采用天朝流行的话,“由于种种原因”本人已接近一年半没有写博客了,最近回想起来,很多东西即便再小也得慢慢积累,更何况前两章之后就没有了,很多网友表示比较期待后面的文字,不能做一个太监了事,打算还是继续写完,给被吊了胃口这么久的朋友表示深深地歉意。
这一章要讲的是winpcap核心编程,首先来看一下sniffer程序的整体框架,程序主要由三个部分构成,其示意图如下:
其中,winpcap对数据的捕获主要在cmcf6Dlg.cpp中完成(偷了些懒,就没有把界面与这部分程序分开了,我得承认这不是一个好习惯),一些功能函数如解析数据包等程序在utilities.cpp中完成,协议包数据结构及类型定义在Protocol.h完成。
winpcap的主要流程如下:
1) 调用pcap_findalldevs()获得网卡接口信息,一台计算机上可能有很多个网卡接口,知道有哪些接口是非常有必要的。
//初始化winpcap int Cmcf6Dlg::lixsniff_initCap() { devCount = 0; if(pcap_findalldevs(&alldev, errbuf) ==-1) return -1; for(dev=alldev;dev;dev=dev->next) devCount++; //记录设备数 return 0; }
其中 alldev与dev声明如下,主要是用来记录查找到的网卡设备
pcap_if_t *alldev;
pcap_if_t *dev;
2) 在获取了网卡接口信息后,即可调用pcap_open_live()打开指定网卡接口,winpcap将在此接口上侦听数据
<pre name="code" class="cpp">if ((adhandle= pcap_open_live(dev->name, // 设备名 65536, //捕获数据包长度 1, // 混杂模式 (非0意味着是混杂模式) 1000, // 读超时设置 errbuf // 错误信息 )) == NULL) { MessageBox(_T("无法打开接口:"+CString(dev->description))); pcap_freealldevs(alldev); return -1; }
3) 调用pcap_datalink()、pcap_compile()、pcap_setfilter()分别检查是否是以太网,并对过滤器进行设置。网络中过来的数据有些可能不是以太网数据,这样的数据我们处理不了,所以首先要进行一个检查;而过滤器是什么呢,简单的说,网络中过来的数据是不同层次、不同协议的,过滤器的作用就是可以设定一些的规则来查看你想要的数据包,如指定只需要TCP包。
/*检查是否为以太网*/ if(pcap_datalink(adhandle)!=DLT_EN10MB) { MessageBox(_T("这不适合于非以太网的网络!")); pcap_freealldevs(alldev); return -1; } /*编译过滤器*/ if(0==filter_index) { char filter[] = ""; if (pcap_compile(adhandle, &fcode, filter, 1, netmask) <0 ) { MessageBox(_T("语法错误,无法编译过滤器")); pcap_freealldevs(alldev); return -1; } }else{ CString str; char *filter; int len,x; this->m_comboBoxRule.GetLBText(filter_index,str); len = str.GetLength()+1; filter = (char*)malloc(len); for(x=0;x<len;x++) { filter[x] = str.GetAt(x); } if (pcap_compile(adhandle, &fcode, filter, 1, netmask) <0 ) { MessageBox(_T("语法错误,无法编译过滤器")); pcap_freealldevs(alldev); return -1; } } /*设置过滤器*/ if (pcap_setfilter(adhandle, &fcode)<0) { MessageBox(_T("设置过滤器错误")); pcap_freealldevs(alldev); return -1; }
4) 调用pcap_dump_open()先创建一个文件,捕获的数据将会存储到此文件中,后面捕获的数据包将会实时地写入一个临时文件,文件默认存储在工程中的SaveData文件中,文件名为存储时的时间,如在2010年10月10日14:15:16存储的,那么其文件名即为20101010141516,在捕获数据结束时,用户可以选择将此文件存储于指定路径。
dumpfile = pcap_dump_open(adhandle, filepath); if(dumpfile==NULL) { MessageBox(_T("文件创建错误!")); return -1; }
5) 完成以上设置后,即可开始捕获数据包了。调用CreateThread()创建一个新的线程,调用lixsinff_CapThread()函数在线程中完成数据包的捕获工作。为什么要新建一个线程来完成这项工作?那是因为我们的主进程是一个Dialog(对话框),它主要的任务是处理界面交互,而数据捕获是一项后台工作,将数据包的捕获与界面进程分离,可以提高程序效率,避免了二者的干扰。
/*接收数据,新建线程处理*/ LPDWORD threadCap=NULL; m_ThreadHandle=CreateThread(NULL,0,lixsinff_CapThread,this,0,threadCap); if(m_ThreadHandle==NULL) { int code=GetLastError(); CString str; str.Format(_T("创建线程错误,代码为%d."),code); MessageBox(str); return -1; }6)在lixsinff_CapThread()中调用pcap_next_ex()函数进行数据包捕获,每到达一个数据包,调用自定义的包处理函数analyze_frame()完成对捕获数据的解析 。注:对于analyze_frame()函数将在第五章专门介绍其工作流程。
while((res = pcap_next_ex( pthis->adhandle, &header, &pkt_data)) >= 0) { if(res == 0) //超时 continue; struct datapkt *data = (struct datapkt*)malloc(sizeof(struct datapkt)); memset(data,0,sizeof(struct datapkt)); if(NULL == data) { MessageBox(NULL,_T("空间已满,无法接收新的数据包"),_T("Error"),MB_OK); return -1; } //分析出错或所接收数据包不在处理范围内 if(analyze_frame(pkt_data,data,&(pthis->npacket))<0) continue; …….(以下省略) }
7) 经过analyze_frame()函数处理后将相关数据更新到GUI。这一点第六章会讲到。
以下是cmcf6Dlg.h以及cmcf6Dlg.cpp的源代码,也就是我们的主程序代码,在代码中可以看到完整的实现过程,实际上对于如何将数据写到GUI上已经大体从这里可以看得出来了:)
下一章:要想从此过,留下协议头——各层网络协议头的实现
cmcf6Dlg.h:
// mcf6Dlg.h : 头文件 // #pragma once #include "afxcmn.h" #include "afxwin.h" #include"pcap.h" #include "Protocol.h" #include "utilities.h" // Cmcf6Dlg 对话框 class Cmcf6Dlg : public CDialog { // 构造 public: Cmcf6Dlg(CWnd* pParent = NULL); // 标准构造函数 /////////////////////////////////////////////[my fuction]////////////////////////////////////////////// int lixsniff_initCap(); int lixsniff_startCap(); int lixsniff_updateTree(int index); int lixsniff_updateEdit(int index); int lixsniff_updateNPacket(); int lixsniff_saveFile(); int lixsniff_readFile(CString path); //////////////////////////////////////////////[my data]///////////////////////////////////////////// int devCount; struct pktcount npacket; //各类数据包计数 char errbuf[PCAP_ERRBUF_SIZE]; pcap_if_t *alldev; pcap_if_t *dev; pcap_t *adhandle; pcap_dumper_t *dumpfile; char filepath[512]; // 文件保存路径 char filename[64]; // 文件名称 HANDLE m_ThreadHandle; //线程 CPtrList m_pktList; //捕获包所存放的链表 // 对话框数据 enum { IDD = IDD_MCF6_DIALOG }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 // 实现 protected: HICON m_hIcon; // 生成的消息映射函数 virtual BOOL OnInitDialog(); afx_msg void OnSysCommand(UINT nID, LPARAM lParam); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); DECLARE_MESSAGE_MAP() public: CListCtrl m_listCtrl; CComboBox m_comboBox; CComboBox m_comboBoxRule; CTreeCtrl m_treeCtrl; CEdit m_edit; afx_msg void OnBnClickedButton1(); afx_msg void OnBnClickedButton2(); CButton m_buttonStart; CButton m_buttonStop; CPtrList m_localDataList; //保存被本地化后的数据包 CPtrList m_netDataList; //保存从网络中直接获取的数据包 CBitmapButton m_bitButton ; //图片按钮 int npkt; afx_msg void OnLvnItemchangedList1(NMHDR *pNMHDR, LRESULT *pResult); CEdit m_editNTcp; CEdit m_editNUdp; CEdit m_editNIcmp; CEdit m_editNIp; CEdit m_editNArp; CEdit m_editNHttp; CEdit m_editNOther; CEdit m_editNSum; afx_msg void OnNMCustomdrawList1(NMHDR *pNMHDR, LRESULT *pResult); afx_msg void OnBnClickedButton5(); CButton m_buttonSave; CButton m_buttonRead; afx_msg void OnBnClickedButton4(); CEdit m_editNIpv4; CEdit m_editIcmpv6; };
cmcf6Dlg.cpp:
// mcf6Dlg.cpp : 实现文件 // #include "stdafx.h" #include "mcf6.h" #include "mcf6Dlg.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // 用于应用程序“关于”菜单项的 CAboutDlg 对话框 DWORD WINAPI lixsinff_CapThread(LPVOID lpParameter); class CAboutDlg : public CDialog { public: CAboutDlg(); // 对话框数据 enum { IDD = IDD_ABOUTBOX }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 // 实现 protected: DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) END_MESSAGE_MAP() // Cmcf6Dlg 对话框 Cmcf6Dlg::Cmcf6Dlg(CWnd* pParent /*=NULL*/) : CDialog(Cmcf6Dlg::IDD, pParent) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void Cmcf6Dlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); DDX_Control(pDX, IDC_LIST1, m_listCtrl); DDX_Control(pDX, IDC_COMBO1, m_comboBox); DDX_Control(pDX, IDC_COMBO2, m_comboBoxRule); DDX_Control(pDX, IDC_TREE1, m_treeCtrl); DDX_Control(pDX, IDC_EDIT1, m_edit); DDX_Control(pDX, IDC_BUTTON1, m_buttonStart); DDX_Control(pDX, IDC_BUTTON2, m_buttonStop); DDX_Control(pDX, IDC_EDIT2, m_editNTcp); DDX_Control(pDX, IDC_EDIT3, m_editNUdp); DDX_Control(pDX, IDC_EDIT4, m_editNIcmp); DDX_Control(pDX, IDC_EDIT5, m_editNIp); DDX_Control(pDX, IDC_EDIT6, m_editNArp); DDX_Control(pDX, IDC_EDIT7, m_editNHttp); DDX_Control(pDX, IDC_EDIT8, m_editNOther); DDX_Control(pDX, IDC_EDIT9, m_editNSum); DDX_Control(pDX, IDC_BUTTON5, m_buttonSave); DDX_Control(pDX, IDC_BUTTON4, m_buttonRead); DDX_Control(pDX, IDC_EDIT10, m_editNIpv4); DDX_Control(pDX, IDC_EDIT11, m_editIcmpv6); } BEGIN_MESSAGE_MAP(Cmcf6Dlg, CDialog) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() //}}AFX_MSG_MAP ON_BN_CLICKED(IDC_BUTTON1, &Cmcf6Dlg::OnBnClickedButton1) ON_BN_CLICKED(IDC_BUTTON2, &Cmcf6Dlg::OnBnClickedButton2) ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST1, &Cmcf6Dlg::OnLvnItemchangedList1) ON_NOTIFY(NM_CUSTOMDRAW, IDC_LIST1, &Cmcf6Dlg::OnNMCustomdrawList1) ON_BN_CLICKED(IDC_BUTTON5, &Cmcf6Dlg::OnBnClickedButton5) ON_BN_CLICKED(IDC_BUTTON4, &Cmcf6Dlg::OnBnClickedButton4) END_MESSAGE_MAP() // Cmcf6Dlg 消息处理程序 BOOL Cmcf6Dlg::OnInitDialog() { CDialog::OnInitDialog(); // 将“关于...”菜单项添加到系统菜单中。 // IDM_ABOUTBOX 必须在系统命令范围内。 ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动 // 执行此操作 SetIcon(m_hIcon, TRUE); // 设置大图标 SetIcon(m_hIcon, FALSE); // 设置小图标 ShowWindow(SW_MINIMIZE); // TODO: 在此添加额外的初始化代码 m_listCtrl.SetExtendedStyle(LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES); m_listCtrl.InsertColumn(0,_T("编号"),3,30); //1表示右,2表示中,3表示左 m_listCtrl.InsertColumn(1,_T("时间"),3,130); m_listCtrl.InsertColumn(2,_T("长度"),3,72); m_listCtrl.InsertColumn(3,_T("源MAC地址"),3,140); m_listCtrl.InsertColumn(4,_T("目的MAC地址"),3,140); m_listCtrl.InsertColumn(5,_T("协议"),3,70); m_listCtrl.InsertColumn(6,_T("源IP地址"),3,145); m_listCtrl.InsertColumn(7,_T("目的IP地址"),3,145); m_comboBox.AddString(_T("请选择一个网卡接口(必选)")); m_comboBoxRule.AddString(_T("请选择过滤规则(可选)")); if(lixsniff_initCap()<0) return FALSE; /*初始化接口列表*/ for(dev=alldev;dev;dev=dev->next) { if(dev->description) m_comboBox.AddString(CString(dev->description)); //////////////////////////////Problem 1字符集问题 } /*初始化过滤规则列表*/ m_comboBoxRule.AddString(_T("tcp")); m_comboBoxRule.AddString(_T("udp")); m_comboBoxRule.AddString(_T("ip")); m_comboBoxRule.AddString(_T("icmp")); m_comboBoxRule.AddString(_T("arp")); m_comboBox.SetCurSel(0); m_comboBoxRule.SetCurSel(0); m_buttonStop.EnableWindow(FALSE); m_buttonSave.EnableWindow(FALSE); //m_bitButton.RedrawWindow(); /////////////////////////////////////////////////////////////////////////////////////////////////listControl用法 //int nitem = m_listCtrl.InsertItem(0,_T("hello")); /*char buf[5]; itoa(nitem,buf,10); MessageBox(CString(buf));*/ /*m_listCtrl.SetItemText(nitem,1,_T("jak")); m_listCtrl.SetItemText(nitem,2,_T("bub")); m_listCtrl.SetItemText(nitem,3,_T("coco")); m_listCtrl.SetItemText(nitem,4,_T("haha"));*/ return TRUE; // 除非将焦点设置到控件,否则返回 TRUE } void Cmcf6Dlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialog::OnSysCommand(nID, lParam); } } // 如果向对话框添加最小化按钮,则需要下面的代码 // 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序, // 这将由框架自动完成。 void Cmcf6Dlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // 用于绘制的设备上下文 SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); // 使图标在工作区矩形中居中 int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // 绘制图标 dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } } //当用户拖动最小化窗口时系统调用此函数取得光标 //显示。 HCURSOR Cmcf6Dlg::OnQueryDragIcon() { return static_cast<HCURSOR>(m_hIcon); } /////////////////////////////////////////[事件函数]/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //开始按钮 void Cmcf6Dlg::OnBnClickedButton1() { // TODO: 在此添加控件通知处理程序代码 //如果已经有数据了,提示保存数据 if(this->m_localDataList.IsEmpty() == FALSE) { if(MessageBox(_T("确认不保存数据?"),_T("警告"),MB_YESNO)==IDNO) { this->lixsniff_saveFile(); } } this->npkt =1; //重新计数 this->m_localDataList.RemoveAll(); //每次一开始就将以前存的数据清空掉 this->m_netDataList.RemoveAll(); memset(&(this->npacket),0,sizeof(struct pktcount)); this->lixsniff_updateNPacket(); if(this->lixsniff_startCap()<0) return; this->m_listCtrl.DeleteAllItems(); this->m_treeCtrl.DeleteAllItems(); this->m_edit.SetWindowTextW(_T("")); this->m_buttonStart.EnableWindow(FALSE); this->m_buttonStop.EnableWindow(TRUE); this->m_buttonSave.EnableWindow(FALSE); } //结束按钮 void Cmcf6Dlg::OnBnClickedButton2() { // TODO: 在此添加控件通知处理程序代码 if(NULL == this->m_ThreadHandle ) return; if(TerminateThread(this->m_ThreadHandle,-1)==0) { MessageBox(_T("关闭线程错误,请稍后重试")); return; } this->m_ThreadHandle = NULL; this->m_buttonStart.EnableWindow(TRUE); this->m_buttonStop.EnableWindow(FALSE); this->m_buttonSave.EnableWindow(TRUE); } //列表 void Cmcf6Dlg::OnLvnItemchangedList1(NMHDR *pNMHDR, LRESULT *pResult) { LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR); // TODO: 在此添加控件通知处理程序代码 int index; index = this->m_listCtrl.GetHotItem(); if(index>this->m_localDataList.GetCount()-1) return; this->lixsniff_updateEdit(index); this->lixsniff_updateTree(index); *pResult = 0; } //保存按钮 void Cmcf6Dlg::OnBnClickedButton5() { // TODO: 在此添加控件通知处理程序代码 if(this->lixsniff_saveFile()<0) return; } //读取按钮 void Cmcf6Dlg::OnBnClickedButton4() { // TODO: 在此添加控件通知处理程序代码 //读取之前将ListCtrl清空 this->m_listCtrl.DeleteAllItems(); this->npkt =1; //列表重新计数 this->m_localDataList.RemoveAll(); //每次一开始就将以前存的数据清空掉 this->m_netDataList.RemoveAll(); memset(&(this->npacket),0,sizeof(struct pktcount));//各类包计数清空 //打开文件对话框 CFileDialog FileDlg(TRUE ,_T(".lix"),NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT); FileDlg.m_ofn.lpstrInitialDir=_T("c:\\"); if(FileDlg.DoModal()==IDOK) { int ret = this->lixsniff_readFile(FileDlg.GetPathName()); if(ret < 0) return; } } //改变ListCtrl每行颜色 void Cmcf6Dlg::OnNMCustomdrawList1(NMHDR *pNMHDR, LRESULT *pResult) { //LPNMCUSTOMDRAW pNMCD = reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR); LPNMLVCUSTOMDRAW pNMCD = (LPNMLVCUSTOMDRAW)pNMHDR; *pResult = 0; // TODO: 在此添加控件通知处理程序代码 if(CDDS_PREPAINT==pNMCD->nmcd.dwDrawStage) { *pResult = CDRF_NOTIFYITEMDRAW; }else if(CDDS_ITEMPREPAINT ==pNMCD->nmcd.dwDrawStage){ COLORREF crText; char buf[10]; memset(buf,0,10); POSITION pos = this->m_localDataList.FindIndex(pNMCD->nmcd.dwItemSpec); struct datapkt * local_data = (struct datapkt *)this->m_localDataList.GetAt(pos); strcpy(buf,local_data->pktType); if(strcmp(buf,"IPV6")==0) crText = RGB(111,224,254); else if(strcmp(buf,"UDP")==0) crText = RGB(194,195,252); else if(strcmp(buf,"TCP")==0) crText = RGB(230,230,230); else if(strcmp(buf,"ARP")==0) crText = RGB(226,238,227); else if(strcmp(buf,"ICMP")==0) crText = RGB(49,164,238); else if(strcmp(buf,"HTTP")==0) crText = RGB(238,232,180); else if(strcmp(buf,"ICMPv6")==0) crText = RGB(189,254,76); pNMCD->clrTextBk =crText; *pResult = CDRF_DODEFAULT; } } //////////////////////////////////////////[功能函数]/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //初始化winpcap int Cmcf6Dlg::lixsniff_initCap() { devCount = 0; if(pcap_findalldevs(&alldev, errbuf) ==-1) return -1; for(dev=alldev;dev;dev=dev->next) devCount++; return 0; } //开始捕获 int Cmcf6Dlg::lixsniff_startCap() { int if_index,filter_index,count; u_int netmask; struct bpf_program fcode; lixsniff_initCap(); //获得接口和过滤器索引 if_index = this->m_comboBox.GetCurSel(); filter_index = this->m_comboBoxRule.GetCurSel(); if(0==if_index || CB_ERR == if_index) { MessageBox(_T("请选择一个合适的网卡接口")); return -1; } if(CB_ERR == filter_index) { MessageBox(_T("过滤器选择错误")); return -1; } /*获得选中的网卡接口*/ dev=alldev; for(count=0;count<if_index-1;count++) dev=dev->next; if ((adhandle= pcap_open_live(dev->name, // 设备名 65536, //捕获数据包长度 1, // 混杂模式 (非0意味着是混杂模式) 1000, // 读超时设置 errbuf // 错误信息 )) == NULL) { MessageBox(_T("无法打开接口:"+CString(dev->description))); pcap_freealldevs(alldev); return -1; } /*检查是否为以太网*/ if(pcap_datalink(adhandle)!=DLT_EN10MB) { MessageBox(_T("这不适合于非以太网的网络!")); pcap_freealldevs(alldev); return -1; } if(dev->addresses!=NULL) netmask=((struct sockaddr_in *)(dev->addresses->netmask))->sin_addr.S_un.S_addr; else netmask=0xffffff; //编译过滤器 if(0==filter_index) { char filter[] = ""; if (pcap_compile(adhandle, &fcode, filter, 1, netmask) <0 ) { MessageBox(_T("语法错误,无法编译过滤器")); pcap_freealldevs(alldev); return -1; } }else{ CString str; char *filter; int len,x; this->m_comboBoxRule.GetLBText(filter_index,str); len = str.GetLength()+1; filter = (char*)malloc(len); for(x=0;x<len;x++) { filter[x] = str.GetAt(x); } if (pcap_compile(adhandle, &fcode, filter, 1, netmask) <0 ) { MessageBox(_T("语法错误,无法编译过滤器")); pcap_freealldevs(alldev); return -1; } } //设置过滤器 if (pcap_setfilter(adhandle, &fcode)<0) { MessageBox(_T("设置过滤器错误")); pcap_freealldevs(alldev); return -1; } /* 设置数据包存储路径*/ CFileFind file; char thistime[30]; struct tm *ltime; memset(filepath,0,512); memset(filename,0,64); if(!file.FindFile(_T("SavedData"))) { CreateDirectory(_T("SavedData"),NULL); } time_t nowtime; time(&nowtime); ltime=localtime(&nowtime); strftime(thistime,sizeof(thistime),"%Y%m%d %H%M%S",ltime); strcpy(filepath,"SavedData\\"); strcat(filename,thistime); strcat(filename,".lix"); strcat(filepath,filename); dumpfile = pcap_dump_open(adhandle, filepath); if(dumpfile==NULL) { MessageBox(_T("文件创建错误!")); return -1; } pcap_freealldevs(alldev); /*接收数据,新建线程处理*/ LPDWORD threadCap=NULL; m_ThreadHandle=CreateThread(NULL,0,lixsinff_CapThread,this,0,threadCap); if(m_ThreadHandle==NULL) { int code=GetLastError(); CString str; str.Format(_T("创建线程错误,代码为%d."),code); MessageBox(str); return -1; } return 1; } DWORD WINAPI lixsinff_CapThread(LPVOID lpParameter) { int res,nItem ; struct tm *ltime; CString timestr,buf,srcMac,destMac; time_t local_tv_sec; struct pcap_pkthdr *header; //数据包头 const u_char *pkt_data=NULL,*pData=NULL; //网络中收到的字节流数据 u_char *ppkt_data; Cmcf6Dlg *pthis = (Cmcf6Dlg*) lpParameter; if(NULL == pthis->m_ThreadHandle) { MessageBox(NULL,_T("线程句柄错误"),_T("提示"),MB_OK); return -1; } while((res = pcap_next_ex( pthis->adhandle, &header, &pkt_data)) >= 0) { if(res == 0) //超时 continue; struct datapkt *data = (struct datapkt*)malloc(sizeof(struct datapkt)); memset(data,0,sizeof(struct datapkt)); if(NULL == data) { MessageBox(NULL,_T("空间已满,无法接收新的数据包"),_T("Error"),MB_OK); return -1; } //分析出错或所接收数据包不在处理范围内 if(analyze_frame(pkt_data,data,&(pthis->npacket))<0) continue; //将数据包保存到打开的文件中 if(pthis->dumpfile!=NULL) { pcap_dump((unsigned char*)pthis->dumpfile,header,pkt_data); } //更新各类数据包计数 pthis->lixsniff_updateNPacket(); //将本地化后的数据装入一个链表中,以便后来使用 ppkt_data = (u_char*)malloc(header->len); memcpy(ppkt_data,pkt_data,header->len); pthis->m_localDataList.AddTail(data); pthis->m_netDataList.AddTail(ppkt_data); /*预处理,获得时间、长度*/ data->len = header->len; //链路中收到的数据长度 local_tv_sec = header->ts.tv_sec; ltime = localtime(&local_tv_sec); data->time[0] = ltime->tm_year+1900; data->time[1] = ltime->tm_mon+1; data->time[2] = ltime->tm_mday; data->time[3] = ltime->tm_hour; data->time[4] = ltime->tm_min; data->time[5] = ltime->tm_sec; /*为新接收到的数据包在listControl中新建一个item*/ buf.Format(_T("%d"),pthis->npkt); nItem = pthis->m_listCtrl.InsertItem(pthis->npkt,buf); /*显示时间戳*/ timestr.Format(_T("%d/%d/%d %d:%d:%d"),data->time[0], data->time[1],data->time[2],data->time[3],data->time[4],data->time[5]); pthis->m_listCtrl.SetItemText(nItem,1,timestr); //pthis->m_listCtrl.setitem /*显示长度*/ buf.Empty(); buf.Format(_T("%d"),data->len); pthis->m_listCtrl.SetItemText(nItem,2,buf); /*显示源MAC*/ buf.Empty(); buf.Format(_T("%02X-%02X-%02X-%02X-%02X-%02X"),data->ethh->src[0],data->ethh->src[1], data->ethh->src[2],data->ethh->src[3],data->ethh->src[4],data->ethh->src[5]); pthis->m_listCtrl.SetItemText(nItem,3,buf); /*显示目的MAC*/ buf.Empty(); buf.Format(_T("%02X-%02X-%02X-%02X-%02X-%02X"),data->ethh->dest[0],data->ethh->dest[1], data->ethh->dest[2],data->ethh->dest[3],data->ethh->dest[4],data->ethh->dest[5]); pthis->m_listCtrl.SetItemText(nItem,4,buf); /*获得协议*/ pthis->m_listCtrl.SetItemText(nItem,5,CString(data->pktType)); /*获得源IP*/ buf.Empty(); if(0x0806== data->ethh->type) { buf.Format(_T("%d.%d.%d.%d"),data->arph->ar_srcip[0], data->arph->ar_srcip[1],data->arph->ar_srcip[2],data->arph->ar_srcip[3]); }else if(0x0800 == data->ethh->type) { struct in_addr in; in.S_un.S_addr = data->iph->saddr; buf = CString(inet_ntoa(in)); }else if(0x86dd ==data->ethh->type ){ int n; for(n=0;n<8;n++) { if(n<=6) buf.AppendFormat(_T("%02x:"),data->iph6->saddr[n]); else buf.AppendFormat(_T("%02x"),data->iph6->saddr[n]); } } pthis->m_listCtrl.SetItemText(nItem,6,buf); /*获得目的IP*/ buf.Empty(); if(0x0806 == data->ethh->type) { buf.Format(_T("%d.%d.%d.%d"),data->arph->ar_destip[0], data->arph->ar_destip[1],data->arph->ar_destip[2],data->arph->ar_destip[3]); }else if(0x0800 == data->ethh->type){ struct in_addr in; in.S_un.S_addr = data->iph->daddr; buf = CString(inet_ntoa(in)); }else if(0x86dd ==data->ethh->type ){ int n; for(n=0;n<8;n++) { if(n<=6) buf.AppendFormat(_T("%02x:"),data->iph6->daddr[n]); else buf.AppendFormat(_T("%02x"),data->iph6->daddr[n]); } } pthis->m_listCtrl.SetItemText(nItem,7,buf); /*对包计数*/ pthis->npkt++; } return 1; } //更新信息 int Cmcf6Dlg::lixsniff_updateEdit(int index) { POSITION localpos,netpos; localpos = this->m_localDataList.FindIndex(index); netpos = this->m_netDataList.FindIndex(index); struct datapkt* local_data = (struct datapkt*)(this->m_localDataList.GetAt(localpos)); u_char * net_data = (u_char*)(this->m_netDataList.GetAt(netpos)); CString buf; print_packet_hex(net_data,local_data->len,&buf); //this- this->m_edit.SetWindowText(buf); return 1; } //更新统计数据 int Cmcf6Dlg::lixsniff_updateNPacket() { CString str_num; str_num.Format(_T("%d"),this->npacket.n_arp); this->m_editNArp.SetWindowText(str_num); str_num.Format(_T("%d"),this->npacket.n_http); this->m_editNHttp.SetWindowText(str_num); str_num.Format(_T("%d"),this->npacket.n_icmp); this->m_editNIcmp.SetWindowText(str_num); str_num.Format(_T("%d"),this->npacket.n_ip6); this->m_editNIp.SetWindowText(str_num); str_num.Format(_T("%d"),this->npacket.n_other); this->m_editNOther.SetWindowText(str_num); str_num.Format(_T("%d"),this->npacket.n_sum); this->m_editNSum.SetWindowText(str_num); str_num.Format(_T("%d"),this->npacket.n_tcp); this->m_editNTcp.SetWindowText(str_num); str_num.Format(_T("%d"),this->npacket.n_udp); this->m_editNUdp.SetWindowText(str_num); str_num.Format(_T("%d"),this->npacket.n_ip); this->m_editNIpv4.SetWindowText(str_num); str_num.Format(_T("%d"),this->npacket.n_icmp6); this->m_editIcmpv6.SetWindowText(str_num); return 1; } //更新树形控件 int Cmcf6Dlg::lixsniff_updateTree(int index) { POSITION localpos; CString str; int i; this->m_treeCtrl.DeleteAllItems(); localpos = this->m_localDataList.FindIndex(index); struct datapkt* local_data = (struct datapkt*)(this->m_localDataList.GetAt(localpos)); HTREEITEM root = this->m_treeCtrl.GetRootItem(); str.Format(_T("接收到的第%d个数据包"),index+1); HTREEITEM data = this->m_treeCtrl.InsertItem(str,root); /*处理帧数据*/ HTREEITEM frame = this->m_treeCtrl.InsertItem(_T("链路层数据"),data); //源MAC str.Format(_T("源MAC:")); for(i=0;i<6;i++) { if(i<=4) str.AppendFormat(_T("%02x-"),local_data->ethh->src[i]); else str.AppendFormat(_T("%02x"),local_data->ethh->src[i]); } this->m_treeCtrl.InsertItem(str,frame); //目的MAC str.Format(_T("目的MAC:")); for(i=0;i<6;i++) { if(i<=4) str.AppendFormat(_T("%02x-"),local_data->ethh->dest[i]); else str.AppendFormat(_T("%02x"),local_data->ethh->dest[i]); } this->m_treeCtrl.InsertItem(str,frame); //类型 str.Format(_T("类型:0x%02x"),local_data->ethh->type); this->m_treeCtrl.InsertItem(str,frame); /*处理IP、ARP、IPv6数据包*/ if(0x0806 == local_data->ethh->type) //ARP { HTREEITEM arp = this->m_treeCtrl.InsertItem(_T("ARP协议头"),data); str.Format(_T("硬件类型:%d"),local_data->arph->ar_hrd); this->m_treeCtrl.InsertItem(str,arp); str.Format(_T("协议类型:0x%02x"),local_data->arph->ar_pro); this->m_treeCtrl.InsertItem(str,arp); str.Format(_T("硬件地址长度:%d"),local_data->arph->ar_hln); this->m_treeCtrl.InsertItem(str,arp); str.Format(_T("协议地址长度:%d"),local_data->arph->ar_pln); this->m_treeCtrl.InsertItem(str,arp); str.Format(_T("操作码:%d"),local_data->arph->ar_op); this->m_treeCtrl.InsertItem(str,arp); str.Format(_T("发送方MAC:")); for(i=0;i<6;i++) { if(i<=4) str.AppendFormat(_T("%02x-"),local_data->arph->ar_srcmac[i]); else str.AppendFormat(_T("%02x"),local_data->arph->ar_srcmac[i]); } this->m_treeCtrl.InsertItem(str,arp); str.Format(_T("发送方IP:"),local_data->arph->ar_hln); for(i=0;i<4;i++) { if(i<=2) str.AppendFormat(_T("%d."),local_data->arph->ar_srcip[i]); else str.AppendFormat(_T("%d"),local_data->arph->ar_srcip[i]); } this->m_treeCtrl.InsertItem(str,arp); str.Format(_T("接收方MAC:"),local_data->arph->ar_hln); for(i=0;i<6;i++) { if(i<=4) str.AppendFormat(_T("%02x-"),local_data->arph->ar_destmac[i]); else str.AppendFormat(_T("%02x"),local_data->arph->ar_destmac[i]); } this->m_treeCtrl.InsertItem(str,arp); str.Format(_T("接收方IP:"),local_data->arph->ar_hln); for(i=0;i<4;i++) { if(i<=2) str.AppendFormat(_T("%d."),local_data->arph->ar_destip[i]); else str.AppendFormat(_T("%d"),local_data->arph->ar_destip[i]); } this->m_treeCtrl.InsertItem(str,arp); }else if(0x0800 == local_data->ethh->type){ //IP HTREEITEM ip = this->m_treeCtrl.InsertItem(_T("IP协议头"),data); str.Format(_T("版本:%d"),local_data->iph->version); this->m_treeCtrl.InsertItem(str,ip); str.Format(_T("IP头长:%d"),local_data->iph->ihl); this->m_treeCtrl.InsertItem(str,ip); str.Format(_T("服务类型:%d"),local_data->iph->tos); this->m_treeCtrl.InsertItem(str,ip); str.Format(_T("总长度:%d"),local_data->iph->tlen); this->m_treeCtrl.InsertItem(str,ip); str.Format(_T("标识:0x%02x"),local_data->iph->id); this->m_treeCtrl.InsertItem(str,ip); str.Format(_T("段偏移:%d"),local_data->iph->frag_off); this->m_treeCtrl.InsertItem(str,ip); str.Format(_T("生存期:%d"),local_data->iph->ttl); this->m_treeCtrl.InsertItem(str,ip); str.Format(_T("协议:%d"),local_data->iph->proto); this->m_treeCtrl.InsertItem(str,ip); str.Format(_T("头部校验和:0x%02x"),local_data->iph->check); this->m_treeCtrl.InsertItem(str,ip); str.Format(_T("源IP:")); struct in_addr in; in.S_un.S_addr = local_data->iph->saddr; str.AppendFormat(CString(inet_ntoa(in))); this->m_treeCtrl.InsertItem(str,ip); str.Format(_T("目的IP:")); in.S_un.S_addr = local_data->iph->daddr; str.AppendFormat(CString(inet_ntoa(in))); this->m_treeCtrl.InsertItem(str,ip); /*处理传输层ICMP、UDP、TCP*/ if(1 == local_data->iph->proto ) //ICMP { HTREEITEM icmp = this->m_treeCtrl.InsertItem(_T("ICMP协议头"),data); str.Format(_T("类型:%d"),local_data->icmph->type); this->m_treeCtrl.InsertItem(str,icmp); str.Format(_T("代码:%d"),local_data->icmph->code); this->m_treeCtrl.InsertItem(str,icmp); str.Format(_T("序号:%d"),local_data->icmph->seq); this->m_treeCtrl.InsertItem(str,icmp); str.Format(_T("校验和:%d"),local_data->icmph->chksum); this->m_treeCtrl.InsertItem(str,icmp); }else if(6 == local_data->iph->proto){ //TCP HTREEITEM tcp = this->m_treeCtrl.InsertItem(_T("TCP协议头"),data); str.Format(_T(" 源端口:%d"),local_data->tcph->sport); this->m_treeCtrl.InsertItem(str,tcp); str.Format(_T(" 目的端口:%d"),local_data->tcph->dport); this->m_treeCtrl.InsertItem(str,tcp); str.Format(_T(" 序列号:0x%02x"),local_data->tcph->seq); this->m_treeCtrl.InsertItem(str,tcp); str.Format(_T(" 确认号:%d"),local_data->tcph->ack_seq); this->m_treeCtrl.InsertItem(str,tcp); str.Format(_T(" 头部长度:%d"),local_data->tcph->doff); HTREEITEM flag = this->m_treeCtrl.InsertItem(_T(" +标志位"),tcp); str.Format(_T("cwr %d"),local_data->tcph->cwr); this->m_treeCtrl.InsertItem(str,flag); str.Format(_T("ece %d"),local_data->tcph->ece); this->m_treeCtrl.InsertItem(str,flag); str.Format(_T("urg %d"),local_data->tcph->urg); this->m_treeCtrl.InsertItem(str,flag); str.Format(_T("ack %d"),local_data->tcph->ack); this->m_treeCtrl.InsertItem(str,flag); str.Format(_T("psh %d"),local_data->tcph->psh); this->m_treeCtrl.InsertItem(str,flag); str.Format(_T("rst %d"),local_data->tcph->rst); this->m_treeCtrl.InsertItem(str,flag); str.Format(_T("syn %d"),local_data->tcph->syn); this->m_treeCtrl.InsertItem(str,flag); str.Format(_T("fin %d"),local_data->tcph->fin); this->m_treeCtrl.InsertItem(str,flag); str.Format(_T(" 紧急指针:%d"),local_data->tcph->urg_ptr); this->m_treeCtrl.InsertItem(str,tcp); str.Format(_T(" 校验和:0x%02x"),local_data->tcph->check); this->m_treeCtrl.InsertItem(str,tcp); str.Format(_T(" 选项:%d"),local_data->tcph->opt); this->m_treeCtrl.InsertItem(str,tcp); }else if(17 == local_data->iph->proto){ //UDP HTREEITEM udp = this->m_treeCtrl.InsertItem(_T("UDP协议头"),data); str.Format(_T("源端口:%d"),local_data->udph->sport); this->m_treeCtrl.InsertItem(str,udp); str.Format(_T("目的端口:%d"),local_data->udph->dport); this->m_treeCtrl.InsertItem(str,udp); str.Format(_T("总长度:%d"),local_data->udph->len); this->m_treeCtrl.InsertItem(str,udp); str.Format(_T("校验和:0x%02x"),local_data->udph->check); this->m_treeCtrl.InsertItem(str,udp); } }else if(0x86dd == local_data->ethh->type){ //IPv6 HTREEITEM ip6 = this->m_treeCtrl.InsertItem(_T("IPv6协议头"),data); ////////////////////////////////////////////////////////////////////////////////////////// str.Format(_T("版本:%d"),local_data->iph6->flowtype); this->m_treeCtrl.InsertItem(str,ip6); str.Format(_T("流类型:%d"),local_data->iph6->version); this->m_treeCtrl.InsertItem(str,ip6); /////////////////////////////////////////////////////////////////////////////////////////// str.Format(_T("流标签:%d"),local_data->iph6->flowid); this->m_treeCtrl.InsertItem(str,ip6); str.Format(_T("有效载荷长度:%d"),local_data->iph6->plen); this->m_treeCtrl.InsertItem(str,ip6); str.Format(_T("下一个首部:0x%02x"),local_data->iph6->nh); this->m_treeCtrl.InsertItem(str,ip6); str.Format(_T("跳限制:%d"),local_data->iph6->hlim); this->m_treeCtrl.InsertItem(str,ip6); str.Format(_T("源地址:")); int n; for(n=0;n<8;n++) { if(n<=6) str.AppendFormat(_T("%02x:"),local_data->iph6->saddr[n]); else str.AppendFormat(_T("%02x"),local_data->iph6->saddr[n]); } this->m_treeCtrl.InsertItem(str,ip6); str.Format(_T("目的地址:")); for(n=0;n<8;n++) { if(n<=6) str.AppendFormat(_T("%02x:"),local_data->iph6->saddr[n]); else str.AppendFormat(_T("%02x"),local_data->iph6->saddr[n]); } this->m_treeCtrl.InsertItem(str,ip6); /*处理传输层ICMPv6、UDP、TCP*/ if(0x3a== local_data->iph6->nh ) //ICMPv6 { HTREEITEM icmp6 = this->m_treeCtrl.InsertItem(_T("ICMPv6协议头"),data); str.Format(_T("类型:%d"),local_data->icmph6->type); this->m_treeCtrl.InsertItem(str,icmp6); str.Format(_T("代码:%d"),local_data->icmph6->code); this->m_treeCtrl.InsertItem(str,icmp6); str.Format(_T("序号:%d"),local_data->icmph6->seq); this->m_treeCtrl.InsertItem(str,icmp6); str.Format(_T("校验和:%d"),local_data->icmph6->chksum); this->m_treeCtrl.InsertItem(str,icmp6); str.Format(_T("选项-类型:%d"),local_data->icmph6->op_type); this->m_treeCtrl.InsertItem(str,icmp6); str.Format(_T("选项-长度%d"),local_data->icmph6->op_len); this->m_treeCtrl.InsertItem(str,icmp6); str.Format(_T("选项-链路层地址:")); int i; for(i=0;i<6;i++) { if(i<=4) str.AppendFormat(_T("%02x-"),local_data->icmph6->op_ethaddr[i]); else str.AppendFormat(_T("%02x"),local_data->icmph6->op_ethaddr[i]); } this->m_treeCtrl.InsertItem(str,icmp6); }else if(0x06 == local_data->iph6->nh){ //TCP HTREEITEM tcp = this->m_treeCtrl.InsertItem(_T("TCP协议头"),data); str.Format(_T(" 源端口:%d"),local_data->tcph->sport); this->m_treeCtrl.InsertItem(str,tcp); str.Format(_T(" 目的端口:%d"),local_data->tcph->dport); this->m_treeCtrl.InsertItem(str,tcp); str.Format(_T(" 序列号:0x%02x"),local_data->tcph->seq); this->m_treeCtrl.InsertItem(str,tcp); str.Format(_T(" 确认号:%d"),local_data->tcph->ack_seq); this->m_treeCtrl.InsertItem(str,tcp); str.Format(_T(" 头部长度:%d"),local_data->tcph->doff); HTREEITEM flag = this->m_treeCtrl.InsertItem(_T("标志位"),tcp); str.Format(_T("cwr %d"),local_data->tcph->cwr); this->m_treeCtrl.InsertItem(str,flag); str.Format(_T("ece %d"),local_data->tcph->ece); this->m_treeCtrl.InsertItem(str,flag); str.Format(_T("urg %d"),local_data->tcph->urg); this->m_treeCtrl.InsertItem(str,flag); str.Format(_T("ack %d"),local_data->tcph->ack); this->m_treeCtrl.InsertItem(str,flag); str.Format(_T("psh %d"),local_data->tcph->psh); this->m_treeCtrl.InsertItem(str,flag); str.Format(_T("rst %d"),local_data->tcph->rst); this->m_treeCtrl.InsertItem(str,flag); str.Format(_T("syn %d"),local_data->tcph->syn); this->m_treeCtrl.InsertItem(str,flag); str.Format(_T("fin %d"),local_data->tcph->fin); this->m_treeCtrl.InsertItem(str,flag); str.Format(_T(" 紧急指针:%d"),local_data->tcph->urg_ptr); this->m_treeCtrl.InsertItem(str,tcp); str.Format(_T(" 校验和:0x%02x"),local_data->tcph->check); this->m_treeCtrl.InsertItem(str,tcp); str.Format(_T(" 选项:%d"),local_data->tcph->opt); this->m_treeCtrl.InsertItem(str,tcp); }else if(0x11== local_data->iph6->nh){ //UDP HTREEITEM udp = this->m_treeCtrl.InsertItem(_T("UDP协议头"),data); str.Format(_T("源端口:%d"),local_data->udph->sport); this->m_treeCtrl.InsertItem(str,udp); str.Format(_T("目的端口:%d"),local_data->udph->dport); this->m_treeCtrl.InsertItem(str,udp); str.Format(_T("总长度:%d"),local_data->udph->len); this->m_treeCtrl.InsertItem(str,udp); str.Format(_T("校验和:0x%02x"),local_data->udph->check); this->m_treeCtrl.InsertItem(str,udp); } } return 1; } int Cmcf6Dlg::lixsniff_saveFile() { CFileFind find; if(NULL==find.FindFile(CString(filepath))) { MessageBox(_T("保存文件遇到未知意外")); return -1; } //打开文件对话框 CFileDialog FileDlg(FALSE,_T(".lix"),NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT); FileDlg.m_ofn.lpstrInitialDir=_T("c:\\"); if(FileDlg.DoModal()==IDOK) { CopyFile(CString(filepath),FileDlg.GetPathName(),TRUE); } return 1; } int Cmcf6Dlg::lixsniff_readFile(CString path) { int res,nItem,i ; struct tm *ltime; CString timestr,buf,srcMac,destMac; time_t local_tv_sec; struct pcap_pkthdr *header; //数据包头 const u_char *pkt_data=NULL; //网络中收到的字节流数据 u_char *ppkt_data; Cmcf6Dlg *pthis =this; //些代码改造自lixsinff_CapThread,为节约工作量,故保留pthis指针 pcap_t *fp; //首先处理一下路径,利用pcap_open_offline打开文件时, //路径需要用char *类型,不能用CString强制转换后的char * int len = path.GetLength()+1; /////////////////////////////////注意这一个细节,必须要加1,否则会出错 char* charpath = (char *)malloc(len); memset(charpath,0,len); if(NULL==charpath) return -1; for(i=0;i<len;i++) charpath[i] = (char)path.GetAt(i); //打开相关文件 if ((fp = pcap_open_offline( /*(char*)(LPCTSTR)path*/charpath, errbuf)) == NULL) { MessageBox(_T("打开文件错误")+CString(errbuf)); return -1; } while((res = pcap_next_ex(fp, &header, &pkt_data)) >= 0) { struct datapkt *data = (struct datapkt*)malloc(sizeof(struct datapkt)); memset(data,0,sizeof(struct datapkt)); if(NULL == data) { MessageBox(_T("空间已满,无法接收新的数据包")); return -1; } //分析出错或所接收数据包不在处理范围内 if(analyze_frame(pkt_data,data,&(pthis->npacket))<0) continue; //更新各类数据包计数 pthis->lixsniff_updateNPacket(); //将本地化后的数据装入一个链表中,以便后来使用 ppkt_data = (u_char*)malloc(header->len); memcpy(ppkt_data,pkt_data,header->len); pthis->m_localDataList.AddTail(data); pthis->m_netDataList.AddTail(ppkt_data); /*预处理,获得时间、长度*/ data->len = header->len; //链路中收到的数据长度 local_tv_sec = header->ts.tv_sec; ltime = localtime(&local_tv_sec); data->time[0] = ltime->tm_year+1900; data->time[1] = ltime->tm_mon+1; data->time[2] = ltime->tm_mday; data->time[3] = ltime->tm_hour; data->time[4] = ltime->tm_min; data->time[5] = ltime->tm_sec; /*为新接收到的数据包在listControl中新建一个item*/ buf.Format(_T("%d"),pthis->npkt); nItem = pthis->m_listCtrl.InsertItem(pthis->npkt,buf); /*显示时间戳*/ timestr.Format(_T("%d/%d/%d %d:%d:%d"),data->time[0], data->time[1],data->time[2],data->time[3],data->time[4],data->time[5]); pthis->m_listCtrl.SetItemText(nItem,1,timestr); /*显示长度*/ buf.Empty(); buf.Format(_T("%d"),data->len); pthis->m_listCtrl.SetItemText(nItem,2,buf); /*显示源MAC*/ buf.Empty(); buf.Format(_T("%02X-%02X-%02X-%02X-%02X-%02X"),data->ethh->src[0],data->ethh->src[1], data->ethh->src[2],data->ethh->src[3],data->ethh->src[4],data->ethh->src[5]); pthis->m_listCtrl.SetItemText(nItem,3,buf); /*显示目的MAC*/ buf.Empty(); buf.Format(_T("%02X-%02X-%02X-%02X-%02X-%02X"),data->ethh->dest[0],data->ethh->dest[1], data->ethh->dest[2],data->ethh->dest[3],data->ethh->dest[4],data->ethh->dest[5]); pthis->m_listCtrl.SetItemText(nItem,4,buf); /*获得协议*/ pthis->m_listCtrl.SetItemText(nItem,5,CString(data->pktType)); /*获得源IP*/ buf.Empty(); if(0x0806== data->ethh->type) { buf.Format(_T("%d.%d.%d.%d"),data->arph->ar_srcip[0], data->arph->ar_srcip[1],data->arph->ar_srcip[2],data->arph->ar_srcip[3]); }else if(0x0800 == data->ethh->type){ struct in_addr in; in.S_un.S_addr = data->iph->saddr; buf = CString(inet_ntoa(in)); }else if(0x86dd == data->ethh->type){ int i; for(i=0;i<8;i++) { if(i<=6) buf.AppendFormat(_T("%02x-"),data->iph6->saddr[i]); else buf.AppendFormat(_T("%02x"),data->iph6->saddr[i]); } } pthis->m_listCtrl.SetItemText(nItem,6,buf); /*获得目的IP*/ buf.Empty(); if(0x0806 == data->ethh->type) { buf.Format(_T("%d.%d.%d.%d"),data->arph->ar_destip[0], data->arph->ar_destip[1],data->arph->ar_destip[2],data->arph->ar_destip[3]); }else if(0x0800 == data->ethh->type) { struct in_addr in; in.S_un.S_addr = data->iph->daddr; buf = CString(inet_ntoa(in)); }else if(0x86dd == data->ethh->type){ int i; for(i=0;i<8;i++) { if(i<=6) buf.AppendFormat(_T("%02x-"),data->iph6->daddr[i]); else buf.AppendFormat(_T("%02x"),data->iph6->daddr[i]); } } pthis->m_listCtrl.SetItemText(nItem,7,buf); /*对包计数*/ pthis->npkt++; } pcap_close(fp); return 1; }