0.1 实现基本框架
// HexView.cpp : implementation file
//
#include "stdafx.h"
#include "SimpleSniffer.h"
#include "HexView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/
// CHexView
IMPLEMENT_DYNCREATE(CHexView, CEditView)
CHexView::CHexView()
{
}
CHexView::~CHexView()
{
}
BEGIN_MESSAGE_MAP(CHexView, CEditView)
//{{AFX_MSG_MAP(CHexView)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/
// CHexView drawing
void CHexView::OnDraw(CDC* pDC)
{
CDocument* pDoc = GetDocument();
// TODO: add draw code here
}
/
// CHexView diagnostics
#ifdef _DEBUG
void CHexView::AssertValid() const
{
CEditView::AssertValid();
}
void CHexView::Dump(CDumpContext& dc) const
{
CEditView::Dump(dc);
}
#endif //_DEBUG
/
// CHexView message handlers
void CHexView::ShowHexText(char *data, int len)
{
}
2.1.4 删除所有 TODO 注释
// DevSelector.cpp : implementation file
//
#include "stdafx.h"
#include "SimpleSniffer.h"
#include "DevSelector.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/
// CDevSelector dialog
CDevSelector::CDevSelector(CWnd* pParent /*=NULL*/)
: CDialog(CDevSelector::IDD, pParent)
{
//{{AFX_DATA_INIT(CDevSelector)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
}
void CDevSelector::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CDevSelector)
DDX_Control(pDX, IDC_DEVS, m_devsName);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CDevSelector, CDialog)
//{{AFX_MSG_MAP(CDevSelector)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/
// CDevSelector message handlers
// CDevSelector 初始化的时候获取设备列表
void CDevSelector::InitWinPcap()
{
pcap_if_t *alldevs;
pcap_if_t *d;
char errbuf[PCAP_ERRBUF_SIZE];
if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1){
::AfxMessageBox("获取设备列表失败");
return;
}
for (d = alldevs; d; d = d->next){
this->m_devsName.AddString(d->description);
this->m_devsArray.push_back(d);
}
this->UpdateData(false);
// 默认选中第一个设备, 如果只有一个设备, 直接点确认就可以了
this->m_devsName.SetCurSel(0);
}
// 析构的时候释放设备列表
CDevSelector::~CDevSelector()
{
// 如果获取设备失败, m_devArray 为空, 释放就会出问题
// 因此判断不空之后才调用 pcap_freealldevs
if(!this->m_devsArray.empty())
pcap_freealldevs(*(this->m_devsArray.begin()));
}
// 初始化
BOOL CDevSelector::OnInitDialog()
{
CDialog::OnInitDialog();
this->InitWinPcap();
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
// 点击了对话框的"确定"按钮, pcap_open 选中的设备
void CDevSelector::OnOK()
{
char errbuf[PCAP_ERRBUF_SIZE];
pcap_if_t *d = this->m_devsArray[this->m_devsName.GetCurSel()];
if ((theApp.m_curDev = pcap_open(d->name, /* name of the device */
65536,/* portion of the packet to capture , 65535 guarantees that the whole packet will be captured on all the link layers */
PCAP_OPENFLAG_PROMISCUOUS,/* promiscuous mode */
1000,/* read timeout */
NULL,/* authentication on the remote machine */
errbuf/* error buffer */)) == NULL)
{
::AfxMessageBox("打开适配器失败!");
theApp.m_curDev = NULL;
return;
}
CDialog::OnOK();
}
1.2.9 实现了IPv6的扩展首部 分析
#include "stdafx.h"
#include <iostream>
#include <string.h>
#include "Head.h"
using namespace std;
extern int packet_kind;
extern unsigned char m_SIP[4];
extern unsigned char m_DIP[4];
extern unsigned char m_SIPv6[16];
extern unsigned char m_DIPv6[16];
extern int ipv6;
extern int remain_len;
const CString sign_ip="0800";
const CString sign_arp="0806";
const CString sign_ipv6="86DD";
void Head_Ethernet::analysis(u_char *pkt_data)
{
CString m_kind;
memcpy(D_Mac,pkt_data,6);
memcpy(S_Mac,pkt_data+6,6);
memcpy(kind,pkt_data+12,2);
m_kind.Format("%02X%02X",kind[0],kind[1]);
//判断下一层协议
remain_len=remain_len-14;
if(m_kind.Compare(sign_ip) == 0)
{
next=new Head_IP();
next->analysis(pkt_data+14);
}
else if(m_kind.Compare(sign_arp) == 0)
{
next=new Head_ARP();
next->analysis(pkt_data+14);
}
else if(m_kind.Compare(sign_ipv6) == 0)
{
next=new Head_IPv6();
next->analysis(pkt_data+14);
}
else
{
next=NULL;
packet_kind=0;
}
}
CString Head_Ethernet::my_print()
{
CString m_SMac;
CString m_DMac;
CString m_Kind;
m_SMac.Format("源MAC: %02X-%02X-%02X-%02X-%02X-%02X\r\n",S_Mac[0],S_Mac[1],S_Mac[2],S_Mac[3],S_Mac[4],S_Mac[5]);
m_DMac.Format("目的MAC: %02X-%02X-%02X-%02X-%02X-%02X\r\n",D_Mac[0],D_Mac[1],D_Mac[2],D_Mac[3],D_Mac[4],D_Mac[5]);
m_Kind.Format("类型: %02X%02X\r\n",kind[0],kind[1]);
return "Ethernet首部\r\n"+m_SMac+m_DMac+m_Kind;
}
void Head_802_3::analysis(u_char *pkt_data)
{
CString m_kind;
memcpy(D_Mac,pkt_data,6);
memcpy(S_Mac,pkt_data+6,6);
memcpy(kind,pkt_data+20,2);
m_kind.Format("%02X%02X",kind[0],kind[1]);
//判断下一层协议
remain_len=remain_len-22;
if(m_kind.Compare(sign_ip) == 0)
{
next=new Head_IP();
next->analysis(pkt_data+22);
}
else if(m_kind.Compare(sign_arp) == 0)
{
next=new Head_ARP();
next->analysis(pkt_data+22);
}
else if(m_kind.Compare(sign_ipv6) == 0)
{
next=new Head_IPv6();
next->analysis(pkt_data+22);
}
else
{
next=NULL;
packet_kind=1;
}
}
CString Head_802_3::my_print()
{
CString m_SMac;
CString m_DMac;
CString m_Kind;
m_SMac.Format("源MAC: %02X-%02X-%02X-%02X-%02X-%02X\r\n",S_Mac[0],S_Mac[1],S_Mac[2],S_Mac[3],S_Mac[4],S_Mac[5]);
m_DMac.Format("目的MAC: %02X-%02X-%02X-%02X-%02X-%02X\r\n",D_Mac[0],D_Mac[1],D_Mac[2],D_Mac[3],D_Mac[4],D_Mac[5]);
m_Kind.Format("类型: %02X%02X\r\n",kind[0],kind[1]);
return "802.3帧首部\r\n"+m_SMac+m_DMac+m_Kind;
}
void Head_ARP::analysis(u_char *pkt_data)
{
memcpy(op,pkt_data+6,2);
memcpy(S_Mac,pkt_data+8,6);
memcpy(S_IP,pkt_data+14,4);
memcpy(D_Mac,pkt_data+18,6);
memcpy(D_IP,pkt_data+24,4);
memcpy(m_SIP,pkt_data+14,4);
memcpy(m_DIP,pkt_data+24,4);
ipv6=0;
next=NULL; //ARP就到头了
packet_kind=2;
}
CString Head_ARP::my_print()
{
CString m_OP;
CString m_SMac;
CString m_SIP;
CString m_DMac;
CString m_DIP;
int mOP=0;
mOP=op[0]<<8 | op[1];
m_OP.Format("操作字段:%d\r\n",mOP);
m_SMac.Format("源MAC: %02X-%02X-%02X-%02X-%02X-%02X\r\n",S_Mac[0],S_Mac[1],S_Mac[2],S_Mac[3],S_Mac[4],S_Mac[5]);
m_DMac.Format("目的MAC: %02X-%02X-%02X-%02X-%02X-%02X\r\n",D_Mac[0],D_Mac[1],D_Mac[2],D_Mac[3],D_Mac[4],D_Mac[5]);
m_SIP.Format("源IP: %u.%u.%u.%u\r\n",S_IP[0],S_IP[1],S_IP[2],S_IP[3]);
m_DIP.Format("目的IP: %u.%u.%u.%u\r\n",D_IP[0],D_IP[1],D_IP[2],D_IP[3]);
return "ARP首部\r\n"+m_OP+m_SMac+m_SIP+m_DMac+m_DIP;
}
void Head_IP::analysis(u_char *pkt_data)
{
version=(pkt_data[0] & 0xf0) >> 4;
len=pkt_data[0] & 0x0f;
memcpy(sign,pkt_data+4,2);
TTL=pkt_data[8];
//memcpy(TTl,pkt_date+8,1);
protocol=pkt_data[9] & 0xff;
memcpy(S_IP,pkt_data+12,4);
memcpy(D_IP,pkt_data+16,4);
//设置全局变量
memcpy(m_SIP,pkt_data+12,4);
memcpy(m_DIP,pkt_data+16,4);
ipv6=0;
//下一层协议判断
remain_len=remain_len-len*4;
if(remain_len == 0)
{
next=NULL;
packet_kind=3;
}
else if(protocol == 1)
{
next=new Head_ICMP();
next->analysis(pkt_data+len*4);
}
else if(protocol == 2)
{
next=new Head_IGMP();
next->analysis(pkt_data+len*4);
}
else if(protocol == 6)
{
next=new Head_TCP();
next->analysis(pkt_data+len*4);
}
else if(protocol == 17)
{
next=new Head_UDP();
next->analysis(pkt_data+len*4);
}
else
{
next=NULL;
packet_kind=3;
}
}
CString Head_IP::my_print()
{
CString m_version_len;
CString m_sign;
CString m_TTL;
CString m_SIP;
CString m_DIP;
int mSign=0;
mSign=sign[0]<<8 | sign[1];
m_version_len.Format("版本: %d 长度: %d\r\n",version,len);
m_sign.Format("标识符: %d\r\n",mSign);
m_TTL.Format("存活时间: %u\r\n",TTL);
m_SIP.Format("源IP: %u.%u.%u.%u\r\n",S_IP[0],S_IP[1],S_IP[2],S_IP[3]);
m_DIP.Format("目的IP: %u.%u.%u.%u\r\n",D_IP[0],D_IP[1],D_IP[2],D_IP[3]);
return "IP首部\r\n"+m_version_len+m_sign+m_TTL+m_SIP+m_DIP;
}
void Head_ICMP::analysis(u_char *pkt_data)
{
kind=pkt_data[0] & 0xff;
code=pkt_data[1] & 0xff;
next=NULL; //ICMP就到头了
packet_kind=4;
}
CString Head_ICMP::my_print()
{
CString m_kind;
CString m_code;
m_kind.Format("类型: %d\r\n",kind);
m_code.Format("代码: %d\r\n",code);
return "ICMP首部\r\n"+m_kind+m_code;
}
void Head_UDP::analysis(u_char *pkt_data)
{
memcpy(S_Port,pkt_data,2);
memcpy(D_Port,pkt_data+2,2);
int sPort=S_Port[0]<<8 | S_Port[1];
int dPort=D_Port[0]<<8 | D_Port[1];
if(sPort == 53 || dPort == 53)
{
next=new Head_DNS();
next->analysis(pkt_data+8);
}
else
{
next=NULL;
packet_kind=5;
}
}
CString Head_UDP::my_print()
{
CString m_SPort;
CString m_DPort;
int sPort=0,dPort=0;
sPort=S_Port[0]<<8 | S_Port[1];
dPort=D_Port[0]<<8 | D_Port[1];
//m_SPort.Format("源端口: %02X%02X\r\n",S_Port[0],S_Port[1]);
//m_DPort.Format("目的端口: %02X%02X\r\n",D_Port[0],D_Port[1]);
m_SPort.Format("源端口: %d\r\n",sPort);
m_DPort.Format("目的端口: %d\r\n",dPort);
return "UDP首部\r\n"+m_SPort+m_DPort;
}
void Head_IGMP::analysis(u_char *pkt_data)
{
version=3; //抓到的好像都是IGMPv3
type=pkt_data[0];
memcpy(Multicast,pkt_data+4,4);
next=NULL; //到头了
packet_kind=6;
}
CString Head_IGMP::my_print()
{
CString m_version;
CString m_type;
CString m_Multicast;
m_version.Format("版本: %d\r\n",version);
m_type.Format("类型: %u\r\n",type);
m_Multicast.Format("D类IP地址: %u.%u.%u.%u\r\n",Multicast[0],Multicast[1],Multicast[2],Multicast[3]);
return "IGMP首部\r\n"+m_version+m_type+m_Multicast;
}
void Head_TCP::analysis(u_char *pkt_data)
{
memcpy(S_Port,pkt_data,2);
memcpy(D_Port,pkt_data+2,2);
memcpy(SYN,pkt_data+4,4);
memcpy(ACK,pkt_data+8,4);
memcpy(Size_Window,pkt_data+14,2);
int sPort=S_Port[0]<<8 | S_Port[1];
int dPort=D_Port[0]<<8 | D_Port[1];
len=(pkt_data[12]& 0xf0) >> 4;
remain_len=remain_len-len*4;
if(remain_len == 0)
{
next=NULL;
packet_kind=7;
}
else if(sPort == 80 || dPort == 80)
{
next=new Head_HTTP();
next->analysis(pkt_data+len*4);
}
else if(sPort == 21 || dPort == 21)
{
next=new Head_FTP();
next->analysis(pkt_data+len*4);
}
else
{
next=NULL;
packet_kind=7;
}
}
CString Head_TCP::my_print()
{
CString m_SPort;
CString m_DPort;
CString m_SYN;
CString m_ACK;
CString m_Size_Window;
CString m_len;
int sPort=0,dPort=0;
int mSYN=0,mACK=0;
int mSize_Window;
sPort=S_Port[0]<<8 | S_Port[1];
dPort=D_Port[0]<<8 | D_Port[1];
mSYN=SYN[0]<<24 | SYN[1]<<16 | SYN[2]<<8 | SYN[3];
mACK=ACK[0]<<24 | ACK[1]<<16 | ACK[2]<<8 | ACK[3];
mSize_Window=Size_Window[0]<<8 | Size_Window[1];
m_SPort.Format("源端口: %d\r\n",sPort);
m_DPort.Format("目的端口: %d\r\n",dPort);
//m_SYN.Format("SYN: %d\r\n",mSYN);
//m_ACK.Format("ACK: %d\r\n",mACK);
m_len.Format("长度: %d\r\n",len*4);
m_Size_Window.Format("窗口大小: %d\r\n",mSize_Window);
return "TCP首部\r\n"+m_SPort+m_DPort+m_SYN+m_ACK+m_Size_Window+m_len;
}
void Head_IPv6 :: analysis(u_char *pkt_data)
{
version=(pkt_data[0] & 0xf0) >> 4;
protocol=pkt_data[6] & 0xff;
memcpy(S_IPv6,pkt_data+8,16);
memcpy(D_IPv6,pkt_data+24,16);
//设置全局变量
memcpy(m_SIPv6,pkt_data+8,16);
memcpy(m_DIPv6,pkt_data+24,16);
ipv6=1;
sign=0; //用于标记是否有扩展首部 0:没有 1:有
//处理可选首部
if(protocol == 0) //IPv6中下一个首部是0时有扩展首部
{
protocol=pkt_data[40] & 0xff;
extern_len=pkt_data[41] & 0xff; //扩展首部长度,不包括开始的8个字符
sign=1;
}
//下一层协议判断
remain_len=remain_len-40;
if(remain_len == 0)
{
next=NULL;
packet_kind=8;
}
else if(protocol == 6)
{
next= new Head_TCP();
if(sign ==1)
next->analysis(pkt_data+40+8+extern_len*8);
else
next->analysis(pkt_data+40);
}
else if(protocol == 17)
{
next= new Head_UDP();
if(sign == 1)
next->analysis(pkt_data+40+8+extern_len*8);
else
next->analysis(pkt_data+40);
}
else if(protocol == 58 )
{
next= new Head_ICMP();
if(sign == 1)
next->analysis(pkt_data+40+8+extern_len*8);
else
next->analysis(pkt_data+40);
}
else if(protocol == 2)
{
next=new Head_IGMP();
if(sign == 1)
next->analysis(pkt_data+40+8+extern_len*8);
else
next->analysis(pkt_data+40);
}
else if(protocol ==89)
{
next=new Head_OSPF();
if(sign == 1)
next->analysis(pkt_data+40+8+extern_len*8);
else
next->analysis(pkt_data+40);
}
else
{
next=NULL;
packet_kind=8;
}
}
CString Head_IPv6:: my_print()
{
CString m_version;
CString m_protocol;
CString m_SIP;
CString m_DIP;
m_version.Format("版本: %d\r\n",version);
m_protocol.Format("协议层协议值: %d\r\n",protocol);
m_SIP.Format("源地址:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X\r\n",S_IPv6[0],S_IPv6[1],S_IPv6[2],S_IPv6[3],S_IPv6[4],S_IPv6[5],S_IPv6[6],S_IPv6[7],S_IPv6[8],S_IPv6[9],S_IPv6[10],S_IPv6[11],S_IPv6[12],S_IPv6[13],S_IPv6[14],S_IPv6[15]);
m_DIP.Format("目的地址:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X\r\n",D_IPv6[0],D_IPv6[1],D_IPv6[2],D_IPv6[3],D_IPv6[4],D_IPv6[5],D_IPv6[6],D_IPv6[7],D_IPv6[8],D_IPv6[9],D_IPv6[10],D_IPv6[11],D_IPv6[12],D_IPv6[13],D_IPv6[14],D_IPv6[15]);
return "IPv6首部\r\n"+m_version+m_protocol+m_SIP+m_DIP;
}
void Head_OSPF::analysis(u_char *pkt_data)
{
version=pkt_data[0] & 0xff;
type=pkt_data[1] & 0xff;
memcpy(Router_ID,pkt_data+4,4);
memcpy(Area_ID,pkt_data+8,4);
next=NULL;
packet_kind=9;
}
CString Head_OSPF::my_print()
{
CString m_version;
CString m_type;
CString m_RouterID;
CString m_AreaID;
m_version.Format("版本: %d\r\n",version);
m_type.Format("类型: %d\r\n",type);
m_RouterID.Format("路由器ID: %u.%u.%u.%u\r\n",Router_ID[0],Router_ID[1],Router_ID[2],Router_ID[3]);
m_AreaID.Format("区域ID: %u.%u.%u.%u\r\n",Area_ID[0],Area_ID[1],Area_ID[2],Area_ID[3]);
return "OSPF首部\r\n"+m_version+m_type+m_RouterID+m_AreaID;
}
void Head_DNS::analysis(u_char *pkt_data)
{
memcpy(ID,pkt_data,2);
Question=pkt_data[0]<<8 ||pkt_data[1];
next=NULL;
packet_kind=10;
}
CString Head_DNS::my_print()
{
CString m_ID;
CString m_Question;
m_ID.Format("标识: 0x%02x%02x\r\n",ID[0],ID[1]);
m_Question.Format("问题数: %d\r\n",Question);
return "DNS首部\r\n"+m_ID+m_Question;
}
void Head_HTTP::analysis(u_char *pkt_data)
{
next=NULL;
packet_kind=11;
}
CString Head_HTTP::my_print()
{
return "HTTP首部\r\n";
}
void Head_FTP::analysis(u_char *pkt_data)
{
next=NULL;
packet_kind=12;
}
CString Head_FTP::my_print()
{
return "FTP首部\r\n";
}
2.1.4 删除所有 TODO 注释
// HexView.cpp : implementation file
//
#include "stdafx.h"
#include "SimpleSniffer.h"
#include "HexView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/
// CHexView
IMPLEMENT_DYNCREATE(CHexView, CEditView)
CHexView::CHexView()
{
// CHexView 用于显示十六进制信息
// 初始化 theApp 中的 Hex 指针为 this
theApp.m_editor = dynamic_cast<Hex*>(this);
}
CHexView::~CHexView()
{
}
BEGIN_MESSAGE_MAP(CHexView, CEditView)
//{{AFX_MSG_MAP(CHexView)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/
// CHexView drawing
void CHexView::OnDraw(CDC* pDC)
{
CDocument* pDoc = GetDocument();
}
/
// CHexView diagnostics
#ifdef _DEBUG
void CHexView::AssertValid() const
{
CEditView::AssertValid();
}
void CHexView::Dump(CDumpContext& dc) const
{
CEditView::Dump(dc);
}
#endif //_DEBUG
/
// CHexView message handlers
// 实现十六进制的显示, 是 Hex 的纯虚函数
void CHexView::ShowHexText(char *data, int len)
{
CString result; // 存储最终结果
CString temp; // 临时存储中间结果
int lineHead; // 行首的偏移
for(lineHead = 0; lineHead < len; lineHead += 16)
{
// 打印行首偏移
temp.Format("%04X: ", lineHead);
result += temp;
CString hex; // 一行的16进制字符串形式
CString asc; // 一行的ASCII码形式
int pos; // 行内偏移
int lineLength = len - lineHead >= 16 ? 16 : len - lineHead; // 这行要打印的字节个数
for(pos = 0; pos < lineLength; ++pos)
{
unsigned char c = (unsigned char)data[lineHead + pos];
// 16进制格式
if(pos != 8)
temp.Format(" %02X", c);
else
temp.Format("-%02X", c);
hex += temp;
// ASCII格式
asc += _istprint(c) ? c : '.';
}
result += hex;
if(pos < 16)
{
CString sPad(' ', 3 * (16 - pos));
result += sPad;
}
result += " ";
result += asc;
result += "\r\n";
}
// 显示出来吧!
this->SetWindowText(result);
}
// 初始化, 设置编辑区只读、更改字体
void CHexView::OnInitialUpdate()
{
CEditView::OnInitialUpdate();
static BOOL inited = FALSE;
if(inited) return;
inited = TRUE;
// 以下代码只在首次调用 OnInitialUpdate 时执行
CEdit& control = this->GetEditCtrl();
control.SetReadOnly();// 编辑区只读, 不允许手动更改
// 设置字体为"宋体" 以达到 空格与字母等宽的效果
this->m_Font.CreatePointFont(120, "宋体");
this->SetFont(&this->m_Font, false);
}
全部完成
// InfoView.cpp : implementation file
//
#include "stdafx.h"
#include "SimpleSniffer.h"
#include "InfoView.h"
#include "Thread.h"
#include "Info.h"
#include "Head.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
extern int count;
extern int packet_kind;
extern unsigned char m_SIP[4];
extern unsigned char m_DIP[4];
extern unsigned char m_SIPv6[16];
extern unsigned char m_DIPv6[16];
extern int ipv6;
extern int remain_len;
/
// CInfoView
IMPLEMENT_DYNCREATE(CInfoView, CListView)
CInfoView::CInfoView()
{
theApp.m_infoView = this;
}
CInfoView::~CInfoView()
{
}
BEGIN_MESSAGE_MAP(CInfoView, CListView)
//{{AFX_MSG_MAP(CInfoView)
ON_MESSAGE(WM_TCATCH, OnTCatch)
ON_NOTIFY_REFLECT(NM_CLICK, OnClick)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/
// CInfoView drawing
void CInfoView::OnDraw(CDC* pDC)
{
CDocument* pDoc = GetDocument();
}
/
// CInfoView diagnostics
#ifdef _DEBUG
void CInfoView::AssertValid() const
{
CListView::AssertValid();
}
void CInfoView::Dump(CDumpContext& dc) const
{
CListView::Dump(dc);
}
#endif //_DEBUG
/
// CInfoView message handlers
// 处理抓包线程抓到包的事件, pkt_data 是抓到的包
void CInfoView::OnTCatch(struct pcap_pkthdr *header, u_char *pkt_data)
{
struct tm *ltime;
char timestr[16]; //用于存储时间
CString line_num,m_len,m_smac,m_dmac; //用于输出格式转化
CString m_kind; //用于记录类型
CString m_cntl; //用于测试是不是802.3帧
CString m_packetkind; //用于显示数组包类型
CString m_s_ip; //用于显示源ip
CString m_d_ip; //用于显示目的ip
Info temp_info; //用于添加所捕获的数据包
u_char S_mac[6]; //存源MAC
u_char D_mac[6]; //存目的MAC
u_char Kind[2]; //存以太帧类型
u_char Cntl[1]; //如果是802.3帧,就应该是03
remain_len=header->len; //初始化
//存储数据包
temp_info.header=header;
temp_info.pkt_data=pkt_data;
//处理header获得时间,长度信息
ltime = localtime(&header->ts.tv_sec);
strftime(timestr, sizeof(timestr), "%H:%M:%S", ltime);
line_num.Format("%d", count++); //count是一个全局变量用于记录行号
m_len.Format("%d",header->len);
//处理pkt_data得到详细信息
memcpy(D_mac,pkt_data,6);
memcpy(S_mac,pkt_data+6,6);
memcpy(Kind,pkt_data+12,2);
memcpy(Cntl,pkt_data+16,1);
m_dmac.Format("%02X-%02X-%02X-%02X-%02X-%02X",D_mac[0],D_mac[1],D_mac[2],D_mac[3],D_mac[4],D_mac[5]);
m_smac.Format("%02X-%02X-%02X-%02X-%02X-%02X",S_mac[0],S_mac[1],S_mac[2],S_mac[3],S_mac[4],S_mac[5]);
m_kind.Format("%02X%02X",Kind[0],Kind[1]);
m_cntl.Format("%02X",Cntl[0]);
//第二步详细分析
if(m_kind.Compare("0800")==0 || m_kind.Compare("0806")==0 || m_kind.Compare("86DD")==0)
{
temp_info.m_Head=new Head_Ethernet();
temp_info.m_Head->analysis(pkt_data);
}
else
{
temp_info.m_Head=new Head_802_3();
temp_info.m_Head->analysis(pkt_data);
}
m_info.push_back(temp_info);
if(ipv6==0)
{
m_s_ip.Format("%u.%u.%u.%u",m_SIP[0],m_SIP[1],m_SIP[2],m_SIP[3]);
m_d_ip.Format("%u.%u.%u.%u",m_DIP[0],m_DIP[1],m_DIP[2],m_DIP[3]);
}
else
{
ipv6_normal_print(m_SIPv6,m_s_ip);
ipv6_normal_print(m_DIPv6,m_d_ip);
}
switch(packet_kind){
case 0:m_packetkind="Ethernet";break;
case 1:m_packetkind="802.3";break;
case 2:m_packetkind="ARP";break;
case 3:m_packetkind="IP";break;
case 4:m_packetkind="ICMPv6";break;
case 5:m_packetkind="UDP";break;
case 6:m_packetkind="IGMPv3";break;
case 7:m_packetkind="TCP";break;
case 8:m_packetkind="IPv6";break;
case 9:m_packetkind="OSPF";break;
case 10:m_packetkind="DNS";break;
case 11:m_packetkind="HTTP";break;
case 12:m_packetkind="FTP";break;
}
//在列表中显示
CListCtrl& ctr = this->GetListCtrl();
int row = ctr.InsertItem(ctr.GetItemCount(), line_num); //获得当前所要输出的行号
ctr.SetItemText(row, 1, timestr);
ctr.SetItemText(row, 2, m_len);
ctr.SetItemText(row, 3, m_s_ip);
ctr.SetItemText(row, 4, m_d_ip);
ctr.SetItemText(row, 5, m_packetkind);
// 抓到包后设置文档已修改, 退出的时候就会提醒用户保存 dump 文件
if(theApp.m_dumper)
this->GetDocument()->SetModifiedFlag();
else// 当前是抓pcap文件中的包, 不需要设置已修改标志
;
}
// CInfoView 继承自列表视图(CListView), 这里设置好各个列
void CInfoView::OnInitialUpdate()
{
CListView::OnInitialUpdate();
static BOOL inited = FALSE;
if(inited) return;
inited = TRUE;
// 以下代码只在首次调用 OnInitialUpdate 时执行
theApp.m_display = this->GetSafeHwnd();
CListCtrl& m_list = GetListCtrl();
LONG lStyle;
lStyle = GetWindowLong(m_list.m_hWnd, GWL_STYLE);
lStyle &= ~LVS_TYPEMASK;
lStyle |= LVS_REPORT;
SetWindowLong(m_list.m_hWnd, GWL_STYLE, lStyle);
DWORD dwStyle = m_list.GetExtendedStyle();
dwStyle |= LVS_EX_FULLROWSELECT;
dwStyle |= LVS_EX_GRIDLINES;
m_list.SetExtendedStyle(dwStyle);
m_list.SetBkColor(RGB(200, 200, 200));
m_list.SetTextBkColor(RGB(200, 200, 200));
m_list.SetTextColor(RGB(10, 10, 80));
m_list.InsertColumn( 0, "序号", LVCFMT_CENTER, 50);
m_list.InsertColumn( 1, "时间", LVCFMT_CENTER, 100);
m_list.InsertColumn( 2, "长度", LVCFMT_CENTER,100 );
//第二步详细分析显示
m_list.InsertColumn( 3,"源IP",LVCFMT_CENTER, 300 );
m_list.InsertColumn( 4,"目的IP",LVCFMT_CENTER, 300 );
m_list.InsertColumn( 5,"包类型",LVCFMT_CENTER, 150 );
}
// 点击列表中某行后, 显示它的包类型、16进制形式的包数据
void CInfoView::OnClick(NMHDR* pNMHDR, LRESULT* pResult)
{
NMLISTVIEW* pList = (NMLISTVIEW*)pNMHDR;
CString m_message; //初始化就是空的
Head_Super* head_temp;
int iItem = pList->iItem;
if(iItem != -1)
{
theApp.m_editor->ShowHexText((char*)m_info[iItem].pkt_data, m_info[iItem].header->len);
head_temp=m_info[iItem].m_Head;
while(head_temp!=NULL)
{
m_message=m_message+head_temp->my_print()+"\r\n";
head_temp=head_temp->next;
}
theApp.m_packInfo->ShowPackInfo(m_message);
}
*pResult = 0;
}
// 清空列表, 开始新的抓包前调用这个这个函数
void CInfoView::clearList()
{
count = 0;
this->m_info.clear();
this->GetListCtrl().DeleteAllItems();
}
// 用于标准化ipv6的ip地址
void CInfoView::ipv6_normal_print(unsigned char *ipv6,CString &out)
{
CString ip_temp[8];
int sign_temp[8];
int i,j;
int count=0; //用于标识,只能有一次格式缩进,一般取第一次连续多个零进行缩进
for(i=0,j=0;i<16;i=i+2,j++)
{
ip_temp[j].Format("%02X%02X",ipv6[i],ipv6[i+1]);
if(ip_temp[j].Compare("0000")==0)
sign_temp[j]=0;
else
sign_temp[j]=1;
}
for(i=0;i<8;i++)
{
if(sign_temp[i]==0 && count==0)
{
for(j=i;j<8;j++)
{
if(sign_temp[j]!=0)
break;
}
if(j==8)
out=out+"::";
else
out=out+":";
i=j-1;
count=1;
}
else
{
if(i==0)
out=ip_temp[i];
else
out=out+":"+ip_temp[i];
}
}
}
2.1.4 删除所有 TODO 注释
// MainFrm.cpp : implementation of the CMainFrame class
//
#include "stdafx.h"
#include "SimpleSniffer.h"
#include "MainFrm.h"
#include "InfoView.h"
#include "HexView.h"
#include "PackInfo.h"
#include "DevSelector.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/
// CMainFrame
IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
ON_WM_CREATE()
ON_COMMAND(ID_SELECTSTART, OnSelectstart)
ON_COMMAND(ID_ENDCATCH, OnEndcatch)
ON_UPDATE_COMMAND_UI(ID_SELECTSTART, OnUpdateSelectstart)
ON_UPDATE_COMMAND_UI(ID_ENDCATCH, OnUpdateEndcatch)
ON_MESSAGE(WM_TEXIT, OnTExit)
ON_UPDATE_COMMAND_UI(ID_FILE_SAVE, OnUpdateFileSave)
ON_UPDATE_COMMAND_UI(ID_FILE_SAVE_AS, OnUpdateFileSaveAs)
ON_UPDATE_COMMAND_UI(ID_FILE_OPEN, OnUpdateFileOpen)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
static UINT indicators[] =
{
ID_SEPARATOR, // status line indicator
ID_INDICATOR_CAPS,
ID_INDICATOR_NUM,
ID_INDICATOR_SCRL,
};
/
// CMainFrame construction/destruction
CMainFrame::CMainFrame()
{
}
CMainFrame::~CMainFrame()
{
}
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
{
TRACE0("Failed to create toolbar\n");
return -1; // fail to create
}
if (!m_wndStatusBar.Create(this) ||
!m_wndStatusBar.SetIndicators(indicators,
sizeof(indicators)/sizeof(UINT)))
{
TRACE0("Failed to create status bar\n");
return -1; // fail to create
}
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar);
return 0;
}
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if( !CFrameWnd::PreCreateWindow(cs) )
return FALSE;
return TRUE;
}
/
// CMainFrame diagnostics
#ifdef _DEBUG
void CMainFrame::AssertValid() const
{
CFrameWnd::AssertValid();
}
void CMainFrame::Dump(CDumpContext& dc) const
{
CFrameWnd::Dump(dc);
}
#endif //_DEBUG
/
// CMainFrame message handlers
// 在这里创建3行1列分割窗体
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
theApp.m_control = this->GetSafeHwnd();// CMainFrame 控制线程启动和终止
CRect rc;
// 获取框架窗口客户区的CRect对象
GetClientRect(&rc);
// 创建静态分割窗口,三行一列
if (!m_wndSplitter.CreateStatic(this, 3, 1, WS_CHILD | WS_VISIBLE))
return FALSE;
if (!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CInfoView), CSize(rc.Width(), rc.Height()/3), pContext))
return FALSE;
if (!m_wndSplitter.CreateView(1, 0, RUNTIME_CLASS(CPackInfo), CSize(rc.Width(), rc.Height()/4), pContext))
return FALSE;
if (!m_wndSplitter.CreateView(2, 0, RUNTIME_CLASS(CHexView), CSize(rc.Width(), rc.Height()/2), pContext))
return FALSE;
return TRUE;
}
// 点击了"开始"工具栏按钮, 弹出 CDevSelector 选中设备进行抓包
void CMainFrame::OnSelectstart()
{
CDevSelector selector;
if(IDOK == selector.DoModal() && theApp.m_curDev)
{
// 打开 tmp.pcap 接收包数据
theApp.m_dumper = pcap_dump_open(theApp.m_curDev, theApp.m_tempDumpFilePath);
theApp.startCatch(); // 启动线程抓包了
}
}
// 点击了"终止"工具栏按钮, pcap_breakloop 正在监听的设备
void CMainFrame::OnEndcatch()
{
pcap_breakloop(theApp.m_curDev);
}
// 得到线程退出前发出的 WM_TEXIT 消息, 可以安全地释放各种资源了
void CMainFrame::OnTExit(int exitNum)
{
// 关闭 网卡设备 和 dump文件
pcap_close(theApp.m_curDev);
if(theApp.m_dumper)
pcap_dump_close(theApp.m_dumper);
// 现在开始不再是"正在抓包"了
theApp.m_iscatching = FALSE;
}
// "开始"按钮的使能控制
void CMainFrame::OnUpdateSelectstart(CCmdUI* pCmdUI)
{
pCmdUI->Enable(!theApp.m_iscatching);
}
// "终止"按钮的使能控制
void CMainFrame::OnUpdateEndcatch(CCmdUI* pCmdUI)
{
pCmdUI->Enable(theApp.m_iscatching);
}
// "保存"按钮的使能控制
void CMainFrame::OnUpdateFileSave(CCmdUI* pCmdUI)
{
pCmdUI->Enable(!theApp.m_iscatching);
}
// "另存为"按钮的使能控制
void CMainFrame::OnUpdateFileSaveAs(CCmdUI* pCmdUI)
{
pCmdUI->Enable(!theApp.m_iscatching);
}
// "打开"按钮的使能控制
void CMainFrame::OnUpdateFileOpen(CCmdUI* pCmdUI)
{
pCmdUI->Enable(!theApp.m_iscatching);
2.1.4 删除所有 TODO 注释
2.1.4 删除所有 TODO 注释
…
Latest commit 324d7bf on 24 Dec 2012
2.1.4 删除所有 TODO 注释
// PackInfo.cpp : implementation file
//
#include "stdafx.h"
#include "SimpleSniffer.h"
#include "PackInfo.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/
// CPackInfo
IMPLEMENT_DYNCREATE(CPackInfo, CEditView)
CPackInfo::CPackInfo()
{
// CPackInfo 是用来显示抓到的包的各层PDU详细信息的
theApp.m_packInfo = this;
}
CPackInfo::~CPackInfo()
{
}
BEGIN_MESSAGE_MAP(CPackInfo, CEditView)
//{{AFX_MSG_MAP(CPackInfo)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/
// CPackInfo drawing
void CPackInfo::OnDraw(CDC* pDC)
{
CDocument* pDoc = GetDocument();
}
/
// CPackInfo diagnostics
#ifdef _DEBUG
void CPackInfo::AssertValid() const
{
CEditView::AssertValid();
}
void CPackInfo::Dump(CDumpContext& dc) const
{
CEditView::Dump(dc);
}
#endif //_DEBUG
/
// CPackInfo message handlers
// 初始化中设置编辑区为只读
void CPackInfo::OnInitialUpdate()
{
CEditView::OnInitialUpdate();
static BOOL inited = FALSE;
if(inited) return;
inited = TRUE;
// 以下代码只在首次调用 OnInitialUpdate 时执行
CEdit& control = this->GetEditCtrl();
control.SetReadOnly();// 编辑区只读, 不允许手动更改
}
// 在编辑区中显示一段字符串
void CPackInfo::ShowPackInfo(const CString& info)
{
this->SetWindowText(info);
}
2.1.10 启动新一次抓包前清空列表, 避免混乱
// SimpleSniffer.cpp : Defines the class behaviors for the application.
//
#include "stdafx.h"
#include "SimpleSniffer.h"
#include "MainFrm.h"
#include "SimpleSnifferDoc.h"
#include "InfoView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/
// CSimpleSnifferApp
BEGIN_MESSAGE_MAP(CSimpleSnifferApp, CWinApp)
//{{AFX_MSG_MAP(CSimpleSnifferApp)
ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
// Standard file based document commands
ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
// Standard print setup command
ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup)
END_MESSAGE_MAP()
/
// CSimpleSnifferApp construction
// CSimpleSnifferApp 构造的时候初始化 tmp.pcap 文件的路径, 设置"正在抓包"标志为 FALSE
CSimpleSnifferApp::CSimpleSnifferApp()
{
char buf[1024];
GetCurrentDirectory(sizeof(buf),buf);
this->m_tempDumpFilePath.Format("%s\\tmp.pcap", buf);
this->m_iscatching = FALSE;
}
/
// The one and only CSimpleSnifferApp object
CSimpleSnifferApp theApp;
int count=1;
unsigned char m_SIP[4];
unsigned char m_DIP[4];
unsigned char m_SIPv6[16];
unsigned char m_DIPv6[16];
int ipv6=0; //如果不是ipv6值为0 如果是值为1
int packet_kind=0; //用于记录数据包分析到的最高层类型,0:Ethernet 1:802.3 2:ARP 3:IP 4:ICMP 5:UDP 6:IGMP 7:TCP
int remain_len; //剩余的数据包长度,用于识别端口号为80的http
/
// CSimpleSnifferApp initialization
BOOL CSimpleSnifferApp::InitInstance()
{
AfxEnableControlContainer();
// Standard initialization
// If you are not using these features and wish to reduce the size
// of your final executable, you should remove from the following
// the specific initialization routines you do not need.
#ifdef _AFXDLL
Enable3dControls(); // Call this when using MFC in a shared DLL
#else
Enable3dControlsStatic(); // Call this when linking to MFC statically
#endif
// Change the registry key under which our settings are stored.
SetRegistryKey(_T("Local AppWizard-Generated Applications"));
LoadStdProfileSettings(); // Load standard INI file options (including MRU)
// Register the application's document templates. Document templates
// serve as the connection between documents, frame windows and views.
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CSimpleSnifferDoc),
RUNTIME_CLASS(CMainFrame), // main SDI frame window
RUNTIME_CLASS(CInfoView));
AddDocTemplate(pDocTemplate);
// Parse command line for standard shell commands, DDE, file open
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
// Dispatch commands specified on the command line
if (!ProcessShellCommand(cmdInfo))
return FALSE;
// The one and only window has been initialized, so show and update it.
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
return TRUE;
}
// 启动线程, 开始抓包
void CSimpleSnifferApp::startCatch()
{
this->m_iscatching = TRUE; // 设置"正在抓包"标志为 TRUE
this->m_infoView->clearList(); // 清空之前抓到的包
::AfxBeginThread(ThreadProc, new ThreadParam(m_curDev, m_dumper));// 启动抓包线程
}
/
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
CString m_email;
CString m_github;
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
virtual BOOL OnInitDialog();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
m_email = _T("");
m_github = _T("");
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
DDX_Text(pDX, IDC_EMAIL, m_email);
DDX_Text(pDX, IDC_GITHUB, m_github);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
// App command to run the dialog
void CSimpleSnifferApp::OnAppAbout()
{
CAboutDlg aboutDlg;
aboutDlg.DoModal();
}
/
// CSimpleSnifferApp message handlers
// 关于对话框的初始化, 显示 github地址 和 我们的邮箱
BOOL CAboutDlg::OnInitDialog()
{
CDialog::OnInitDialog();
this->m_github = "https://github.com/1184893257/SimpleSniffer/tree/master/SimpleSniffer";
this->m_email = "1184893257@qq.com";
this->UpdateData(false);
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
2.1.4 删除所有 TODO 注释
// SimpleSnifferDoc.cpp : implementation of the CSimpleSnifferDoc class
//
#include "stdafx.h"
#include "SimpleSniffer.h"
#include "SimpleSnifferDoc.h"
#include "Thread.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/
// CSimpleSnifferDoc
IMPLEMENT_DYNCREATE(CSimpleSnifferDoc, CDocument)
BEGIN_MESSAGE_MAP(CSimpleSnifferDoc, CDocument)
//{{AFX_MSG_MAP(CSimpleSnifferDoc)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/
// CSimpleSnifferDoc construction/destruction
CSimpleSnifferDoc::CSimpleSnifferDoc()
{
}
CSimpleSnifferDoc::~CSimpleSnifferDoc()
{
}
BOOL CSimpleSnifferDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
return TRUE;
}
// 将 src 文件的内容复制到 dest 文件
void copyFile(CFile *src, CFile *dest)
{
char buf[1024];
int n;
while((n = src->Read(buf, sizeof(buf))) > 0)
dest->Write(buf, n);
}
/
// CSimpleSnifferDoc serialization
//串行化中实现 保存/打开 逻辑
void CSimpleSnifferDoc::Serialize(CArchive& ar)
{
CFile *f = ar.GetFile();
// 如果是 tmp.pcap, 报错
if(theApp.m_tempDumpFilePath.Compare(f->GetFilePath()) == 0)
{
CString s;
s.Format("%s 文件用于存储当前抓到的包, 不作他用!", theApp.m_tempDumpFilePath);
::AfxMessageBox(s);
return;
}
// 如果是保存, 将 tmp.pcap 中的内容复制到 f 中
if (ar.IsStoring())
{
CFile src(theApp.m_tempDumpFilePath, CFile::modeRead);
copyFile(&src, f);
src.Close();
}
// 如果是打开, 将该文件中的内容复制到 tmp.pcap, 启动线程从 tmp.pcap 读取包
else
{
// 复制到 tmp.pcap
CFile dest(theApp.m_tempDumpFilePath, CFile::modeWrite | CFile::modeCreate);
copyFile(f, &dest);
dest.Close();
// 打开 tmp.pcap, 侦听, TExit 事件中关闭 tmp.pcap 文件
FILE *fp = fopen(theApp.m_tempDumpFilePath, "rb");
char errbuf[PCAP_ERRBUF_SIZE];
theApp.m_curDev = pcap_fopen_offline(fp, errbuf);
theApp.m_dumper = NULL;
theApp.startCatch(); // 开始抓包, 还设置"正在抓包"标志
}
}
/
// CSimpleSnifferDoc diagnostics
#ifdef _DEBUG
void CSimpleSnifferDoc::AssertValid() const
{
CDocument::AssertValid();
}
void CSimpleSnifferDoc::Dump(CDumpContext& dc) const
{
CDocument::Dump(dc);
}
#endif //_DEBUG
/
// CSimpleSnifferDoc commands
2.1.2 将所有我们改动过的函数加一行总结性注释
#include "stdafx.h"
#include "SimpleSniffer.h"
#include "thread.h"
#include <pcap.h>
// pcap_loop 捕获到一个包后将包数据复制一份 并 发出WM_TCATCH消息
static void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
{
struct pcap_pkthdr *new_header = new struct pcap_pkthdr;
u_char *new_data = new u_char[header->len];
if(param) // param 不是 NULL, 就存入文件
pcap_dump(param, header, pkt_data);
// 复制数据, 发出消息
*new_header = *header;
memcpy(new_data, pkt_data, header->len);
::PostMessage(theApp.m_display, WM_TCATCH, (WPARAM)new_header, (LPARAM)new_data);
}
// 抓包线程的实现
UINT ThreadProc(LPVOID param)
{
ThreadParam *p = (ThreadParam*)param;
// 循环捕获包, 循环可以被 pcap_breakloop 终止
int loopreturn = pcap_loop(p->m_dev, 0, packet_handler, (unsigned char*)p->m_dumper);
delete p;
// 退出前发出 WM_TEXIT 消息
::PostMessage(theApp.m_control, WM_TEXIT, loopreturn, NULL);
return 0;
}