一步一步開發sniffer(Winpcap+MFC)(三)安得廣廈千萬間,先畫藍圖再砌磚——搭建winpcap抓包框架
採用天朝流行的話,“由於種種原因”本人已接近一年半沒有寫部落格了,最近回想起來,很多東西即便再小也得慢慢積累,更何況前兩章之後就沒有了,很多網友表示比較期待後面的文字,不能做一個太監了事,打算還是繼續寫完,給被吊了胃口這麼久的朋友表示深深地歉意。
這一章要講的是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;
}