這一節主要介紹如何獲設置捕獲過濾,這里的過濾是指在捕獲前過濾
設置捕獲過濾主要是在CFilterDlg中完成,也就是對應之前創建的設置過濾規則對話框,如圖:

首先要根據用戶的選擇來生成一個合法的過濾規則字符串,根據WinPcap的要求,合法的過濾規則可以是如下幾種:
1) 表達式支持邏輯操作符,可以使用關鍵字 and、or、not對子表達式進行組合,同時支持使用小括號。
2) 基於協議的過濾要使用協議限定符,協議限定符可以為ip、arp、rarp、tcp、udp等。
3) 基於MAC地址的過濾要使用限定符ether(代表以太網地址)、當該MAC地址僅作為源地址時表達式為ether src mac_addr,僅作為目的地址時,表達式為ether dst mac_addr,既作為源地址又作為目的地址時的表達式為ether host mac_addr。此外應注意mac_addr應該遵從00:E0:4C:E0:38:88的格式,否則編譯過濾器時會出錯。
4) 基於IP地址的過濾應該使用限定符host(代表主機地址)。當該IP地址僅作為源地址時過濾表達式應為 src host ip_addr,僅作為目的地址時的表達式為 dst host ip_addr,既作為源地址又作為目的地址時表達式為 host ip_addr。
5) 基於端口的過濾應使用限定符 port。例如僅接收80端口的數據包則表達式為port 80。
下邊給出兩個例子:
例1:只捕獲arp或icmp數據包。
過濾表達式:arp or (ip and icmp)
例2:捕獲主機192.168.1.23與192.168.1.28之間傳遞的所有UDP數據包。
過濾表達式:(ip and udp)and( host 192.168.1.23 or host 192.168.1.28)
這樣可以用以下代碼來生成一個合法的過濾規則:首先生成一個點擊確定的觸發函數,之后添加如下代碼
1 void CFilterDlg::OnBnClickedOk() 2 { 3 // TODO: 在此添加控件通知處理程序代碼 4 if (1 == m_tcp.GetCheck()) 5 { 6 filtername += _T("(tcp and ip) or "); 7 } 8 if (1 == m_udp.GetCheck()) 9 { 10 filtername += _T("(udp and ip) or "); 11 } 12 if (1 == m_arp.GetCheck()) 13 { 14 filtername += _T("arp or "); 15 } 16 if (1 == m_rarp.GetCheck()) 17 { 18 filtername += _T("rarp or "); 19 } 20 if (1 == m_icmp.GetCheck()) 21 { 22 filtername += _T("(icmp and ip) or "); 23 } 24 if (1 == m_igmp.GetCheck()) 25 { 26 filtername += _T("(igmp and ip) or "); 27 } 28 29 filtername = filtername.Left(filtername.GetLength()-4); //注意去掉最后多余的" or ",否則過濾規則不成立 30 31 CDialogEx::OnOK(); 32 33 }
這里想補充一點關於單選框和復選框的判斷是否選擇的問題
判斷按鈕是否選中:
復選:1 == m_tcp.GetCheck()
單選和復選:不能用GetCheck()可以用通用的if (((CButton *)GetDlgItem(IDC_RADIO1))->GetCheck())用按鈕ID來選擇
在默認設置時兩者也有區別:
復選:m_tcp.SetCheck(1)
單選和復選:CheckDlgButton(IDC_RADIO1, 1)
也就是說復選和單選都可以通過按鈕的ID來設置,而復選又多了自己的一個專門函數用來設置。
回到程序,在生成一段合法的字符串后將filtername返回給主窗口,設置和編譯過濾規則的函數也在主窗口中處理,這些內容在下一節介紹吧
下一節 MFC+WinPcap編寫一個嗅探器之六(分析模塊)
