⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 capturepacketdlg.cpp

📁 ip包解析
💻 CPP
字号:
// CapturePacketDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "afxmt.h"
#include "CapturePacket.h"
#include "CapturePacketDlg.h"


#ifdef _DEBUG
#define new DEBUG_NEW
#endif

//
typedef struct hard_header{
    BYTE	des[6];          // Source port
    BYTE	src[6];          // Destination port
    u_short ftype;            // Datagram length
}hard_header;

typedef struct PacketInfo {
	struct pcap_pkthdr *header;
	const u_char *pkt_data;
} PacketInfo;

#define	MAX_PACKET_BUF	64
PacketInfo CapturePacket[MAX_PACKET_BUF];
int	CaptureHeader,CaptureTail;

pcap_t *adhandle;
// 创建子线程变量
CWinThread *m_Capturer;
CEvent hEventGetPacket;
bool bExit;

UINT Capturer(PVOID hWnd);


// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

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()


// CCapturePacketDlg 对话框



CCapturePacketDlg::CCapturePacketDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CCapturePacketDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CCapturePacketDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_IfList, m_IfList);
	DDX_Control(pDX, IDC_CAPTURE, m_Capture);
	DDX_Control(pDX, IDC_IfInfo, m_IFInfo);
	DDX_Control(pDX, IDC_CaptureInfo, m_CaptureInfo);
	DDX_Control(pDX, IDC_Filter, m_Filter);
	DDX_Control(pDX, IDC_STOP, m_Stop);
}

BEGIN_MESSAGE_MAP(CCapturePacketDlg, CDialog)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
	ON_LBN_SELCHANGE(IDC_IfList, OnLbnSelchangeIflist)
	ON_BN_CLICKED(IDC_CAPTURE, OnBnClickedCapture)
	ON_BN_CLICKED(IDCANCEL, OnBnClickedCancel)
	ON_MESSAGE(WM_PACKET,OnPacket)
	ON_MESSAGE(WM_PACKET_ERR,OnPacketErr)
	
	ON_BN_CLICKED(IDC_STOP, OnBnClickedStop)
END_MESSAGE_MAP()


// CCapturePacketDlg 消息处理程序

BOOL CCapturePacketDlg::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);		// 设置小图标

	// TODO:在此添加额外的初始化代码
	
	//获取本机的接口列表
	pcap_if_t *d;
    char errbuf[PCAP_ERRBUF_SIZE],strbuf[256];
    
    //获得本机的设备列表
    if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL /*无需认证*/, &alldevs, errbuf) == -1)
    {
        sprintf(strbuf,"pcap_findalldevs_ex错误: %s", errbuf); //错误,返回错误信息
		m_IfList.InsertString(-1,strbuf);
		m_Capture.EnableWindow(FALSE);
        return TRUE;
    }
    
    //显示接口列表
    for(d= alldevs; d != NULL; d= d->next)
    {
        sprintf(strbuf,"%s", d->name);
		m_IfList.InsertString(-1,strbuf);
	}
	
	//显示选中接口的详细信息
	m_IfList.SetCurSel(0);
	OnLbnSelchangeIflist();

	return TRUE;  // 除非设置了控件的焦点,否则返回 TRUE
}

void CCapturePacketDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void CCapturePacketDlg::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 CCapturePacketDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

void CCapturePacketDlg::OnLbnSelchangeIflist()
{
	// TODO: 在此添加控件通知处理程序代码
    pcap_if_t *d;
	pcap_addr_t *a;
    char strbuf[256];
    
	m_IfList.GetText(m_IfList.GetCurSel(),strbuf);

    //查找选择的接口
    for(d= alldevs; d != NULL; d= d->next)
        if (strcmp(strbuf,d->name) == 0) break;

	//显示选择接口的详细信息
	m_IFInfo.ResetContent();
	
	sprintf(strbuf,"%s",d->name);
	m_IFInfo.InsertString(-1,strbuf);
    if (d->description)
	{
		sprintf(strbuf,"%s", d->description);
    	m_IFInfo.InsertString(-1,strbuf);
	}

	//获取IP信息
	for(a=d->addresses;a;a=a->next)
	{
        if (a->addr->sa_family==AF_INET)
		{
           	if (a->addr)
			{
				sprintf(strbuf,"  IP地址:%s",iptos(((struct sockaddr_in *)a->addr)->sin_addr.s_addr));
				m_IFInfo.InsertString(-1,strbuf);
			}
            if (a->netmask)
			{
                sprintf(strbuf,"  地址掩码:%s",iptos(((struct sockaddr_in *)a->netmask)->sin_addr.s_addr));
				m_IFInfo.InsertString(-1,strbuf);
			}
            if (a->broadaddr)
			{
                sprintf(strbuf,"  广播地址:%s",iptos(((struct sockaddr_in *)a->broadaddr)->sin_addr.s_addr));
				m_IFInfo.InsertString(-1,strbuf);
			}
            if (a->dstaddr)
			{
				sprintf(strbuf,"  目的地址:%s",iptos(((struct sockaddr_in *)a->dstaddr)->sin_addr.s_addr));
				m_IFInfo.InsertString(-1,strbuf);
			}
		}
	}  
}

// 将数字型的IP地址转换成字符串
char * CCapturePacketDlg::iptos(unsigned long in)
{
	static char output[3*4+3+1];
    BYTE *p;

    p = (u_char *)&in;
    sprintf(output, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
    return output;
}

void CCapturePacketDlg::OnBnClickedCapture()
{
	// TODO: 在此添加控件通知处理程序代码
    pcap_if_t *d;
    char errbuf[PCAP_ERRBUF_SIZE],strbuf[256];
	
	u_int netmask;
	char packet_filter[256];
	struct bpf_program fcode;


	m_IfList.GetText(m_IfList.GetCurSel(),strbuf);

    //查找选择的接口
    for(d= alldevs; d != NULL; d= d->next)
        if (strcmp(strbuf,d->name) == 0) break;

	// 打开接口
    if ( (adhandle= pcap_open(d->name,          // name of the device
                              65536,            // portion of the packet to capture. 
                                                // 65536 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)
    {
        sprintf(strbuf,"接口未能打开。WinPcap不支持%s。", d->name);
		m_CaptureInfo.InsertString(-1,strbuf);
        return;
    }

	//设置过滤规则
	if (m_Filter.GetWindowText(packet_filter,200) != 0)
	{
		if(d->addresses != NULL)
			/* Retrieve the mask of the first address of the interface */
			netmask=((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr;
		else
			/* If the interface is without addresses we suppose to be in a C class network */
			netmask=0xffffff; 

		//compile the filter
	    if (pcap_compile(adhandle, &fcode, packet_filter, 1, netmask) <0 )
		{
			sprintf(strbuf,"过滤规则编译不成功,请检查书写的规则语法是否正确!");
			m_CaptureInfo.InsertString(-1,strbuf);
	        return;
		}
    
        if (pcap_setfilter(adhandle, &fcode)<0)
		{
			sprintf(strbuf,"\nError setting the filter.\n");
			m_CaptureInfo.InsertString(-1,strbuf);
	        return ;
		}
	}

	CaptureHeader=0;
	CaptureTail=0;
	bExit=FALSE;

	m_CaptureInfo.ResetContent();
	m_Capture.EnableWindow(FALSE);
	m_Stop.EnableWindow(TRUE);
	m_IfList.EnableWindow(FALSE);
	m_Filter.EnableWindow(FALSE);
	
	sprintf(strbuf,"监听%s开始......", d->description);
	m_CaptureInfo.InsertString(-1,strbuf);

	m_Capturer=AfxBeginThread(Capturer,NULL,THREAD_PRIORITY_NORMAL);
	
}
   

UINT Capturer(PVOID hWnd)
{
	int	res;

	while (bExit == FALSE)
	{
		res = pcap_next_ex( adhandle, &CapturePacket[CaptureTail].header, &CapturePacket[CaptureTail].pkt_data);
        if (res == 0) continue;            // Timeout elapsed
		if (res >0)
		{
			CaptureTail++;
			if (CaptureTail == MAX_PACKET_BUF) CaptureTail=0;
			AfxGetApp()->m_pMainWnd->PostMessage(WM_PACKET,0,0);
		}
		else
		{
			AfxGetApp()->m_pMainWnd->PostMessage(WM_PACKET_ERR,0,0);
		}
	}
	return 0;
}

void CCapturePacketDlg::OnBnClickedCancel()
{
	// TODO: 在此添加控件通知处理程序代码
	bExit=TRUE;

	OnCancel();
}

LRESULT CCapturePacketDlg::OnPacket(WPARAM wParam, LPARAM lParam)
{
    char strbuf[256];
   	struct tm *ltime;
	char timestr[16];

	hard_header *hh;

	while (CaptureHeader!=CaptureTail)
	{
		sprintf(strbuf,"------------------------------------------------------------------------------------------------------------------------------------------------------------------------");
		m_CaptureInfo.InsertString(-1,strbuf);

		// convert the timestamp to readable format 
		ltime=localtime(&CapturePacket[CaptureHeader].header->ts.tv_sec);
		strftime( timestr, sizeof timestr, "%H:%M:%S", ltime);
        sprintf(strbuf,"%s,%.6d len:%d",timestr, CapturePacket[CaptureHeader].header->ts.tv_usec, CapturePacket[CaptureHeader].header->len);
		m_CaptureInfo.InsertString(-1,strbuf);
			
		hh = (hard_header *) (CapturePacket[CaptureHeader].pkt_data);
	    //print ip addresses and udp ports
		sprintf(strbuf,"目的地址: %02X-%02X-%02X-%02X-%02X-%02X      源地址: %02X-%02X-%02X-%02X-%02X-%02X     帧类型: %04X",
		hh->des[0],hh->des[1],hh->des[2],hh->des[3],hh->des[4],hh->des[5],
		hh->src[0],hh->src[1],hh->src[2],hh->src[3],hh->src[4],hh->src[5],
		ntohs(hh->ftype)
		);
		m_CaptureInfo.InsertString(-1,strbuf);
			
		CaptureHeader++;
		if (CaptureHeader == MAX_PACKET_BUF) CaptureHeader =0;
	}
	return 0;
}


afx_msg LRESULT CCapturePacketDlg::OnPacketErr(WPARAM wParam, LPARAM lParam)
{
	char	strbuf[256];

	sprintf(strbuf,"捕获数据包调用pcap_next_ex出错!");
	m_CaptureInfo.InsertString(-1,strbuf);

	return 0;
}

void CCapturePacketDlg::OnBnClickedStop()
{
	// TODO: 在此添加控件通知处理程序代码
	bExit=TRUE;
	m_Capture.EnableWindow(TRUE);
	m_Stop.EnableWindow(FALSE);
	m_IfList.EnableWindow(TRUE);
	m_Filter.EnableWindow(TRUE);
	pcap_close(adhandle);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -