您的位置:首页 > 其它

网卡混杂模式

2016-04-10 10:58 561 查看

前言

使用原始套接字, 练习网卡混杂模式, 封装了一个UI.

取到IP数据, 用IP头, TCP头, UDP头,ICMP头按照定义进行了读取和显示.

可以分别监听TCP,UDP,ICMP数据



数据得到后,不能显示的太猛了,否则UI挂掉。

让UI定时检测显示数据,而不是来了数据就立即显示。

从混杂模式取数据的速度快于显示速度,如果用UpdateAllViews来调用OnUpdate, UI挂掉了.

工程下载点

编译环境: win7x64 + vc6sp6 + PSDK补丁

srcNetDataViewer_2016_0412_0031.zip

代码预览

// MainDoc.h : interface of the CMainDoc class
//
/////////////////////////////////////////////////////////////////////////////

#if !defined(AFX_MAINDOC_H__E5B7BA53_5BC1_42BF_85B1_F0022F06D5E9__INCLUDED_)
#define AFX_MAINDOC_H__E5B7BA53_5BC1_42BF_85B1_F0022F06D5E9__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "LsCriticalSection.h"
#include "MyThread.h"
#include "ListRowData.h"
#include "net_data_header.h"

#include <list>
using namespace std;

#define WM_MY_UPDATE_VIEW WM_APP + 1000
class CMainDoc : public CDocument
{
protected: // create from serialization only
CMainDoc();
DECLARE_DYNCREATE(CMainDoc)

// Attributes
public:

// Operations
public:

// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CMainDoc)
public:
virtual BOOL OnNewDocument();
virtual void Serialize(CArchive& ar);
//}}AFX_VIRTUAL

// Implementation
public:
virtual ~CMainDoc();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif

protected:

// Generated message map functions
protected:
//{{AFX_MSG(CMainDoc)
afx_msg void OnListenBegin();
afx_msg void OnListenEnd();
afx_msg void OnUpdateListenBegin(CCmdUI* pCmdUI);
afx_msg void OnUpdateListenEnd(CCmdUI* pCmdUI);
afx_msg void OnListenTcp();
afx_msg void OnUpdateListenTcp(CCmdUI* pCmdUI);
afx_msg void OnListenUdp();
afx_msg void OnUpdateListenUdp(CCmdUI* pCmdUI);
afx_msg void OnListenIcmp();
afx_msg void OnUpdateListenIcmp(CCmdUI* pCmdUI);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()

public:
void ShowErrMsg(int iErrSn);
void ShowSocketErrMsg();
void ShowErrMsg();
void ShowThreadMsg(TCHAR* pMsg, eImageIndex ImageIndex);
void ShowThreadMsgRowData(CListRowData* pRowData);
void ClearThreadMsg();

void LockMsg();
void UnLockMsg();
list<CListRowData>& GetListRowData();

BOOL IsThreadRunning();
void StartListenThread();
void StopListenThread();

static unsigned __stdcall ThreadProcNetDataListen(void* pParam);
unsigned ThreadProcNetDataListen();
BOOL fnNetworkProtocolAnalysis(BYTE* pBuf, int iLenRecv); ///< 网络协议分析

BOOL fnNetworkProtocolAnalysis_TCP(int iLenRecv, CListRowData* pRowData, IPHDR* pIpHeader, BYTE* pBuf, int iLenBuf); ///< 网络协议分析-TCP
BOOL fnNetworkProtocolAnalysis_UDP(int iLenRecv, CListRowData* pRowData, IPHDR* pIpHeader, BYTE* pBuf, int iLenBuf); ///< 网络协议分析-UDP
BOOL fnNetworkProtocolAnalysis_ICMP(int iLenRecv, CListRowData* pRowData, IPHDR* pIpHeader, BYTE* pBuf, int iLenBuf); ///< 网络协议分析-ICMP

BOOL fnNetworkProtocolAnalysis_AddData(int iLenRecv, CListRowData* pRowData, BYTE* pBuf, int iLenBuf); ///< 网络协议分析-加入现实数据

void SetListenOptTCP(BOOL bParam);
BOOL GetListenOptTCP();

void SetListenOptUDP(BOOL bParam);
BOOL GetListenOptUDP();

void SetListenOptICMP(BOOL bParam);
BOOL GetListenOptICMP();

private:
void DataInit();
void DataUnInit();
unsigned fnThreadProcNetDataListen(CMyThread& Thread);

private:
list<CListRowData> m_ListRowData;
CLsCriticalSection g_csDispMsg;

CMyThread m_ThreadNetDataListen; ///< 监听网络数据的线程
BOOL m_bListernTCP; ///< 是否监听TCP
BOOL m_bListernUDP; ///< 是否监听UDP
BOOL m_bListernICMP; ///< 是否监听ICMP
};

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_MAINDOC_H__E5B7BA53_5BC1_42BF_85B1_F0022F06D5E9__INCLUDED_)


// MainDoc.cpp : implementation of the CMainDoc class
//

#include "stdafx.h"
#include <MSTcpIP.h> ///< for SIO_RCVALL
#include "NetDataViewer.h"
#include "net_data_header.h"

#include "MainDoc.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CMainDoc

IMPLEMENT_DYNCREATE(CMainDoc, CDocument)

BEGIN_MESSAGE_MAP(CMainDoc, CDocument)
//{{AFX_MSG_MAP(CMainDoc)
ON_COMMAND(IDM_LISTEN_BEGIN, OnListenBegin)
ON_COMMAND(IDM_LISTEN_END, OnListenEnd)
ON_UPDATE_COMMAND_UI(IDM_LISTEN_BEGIN, OnUpdateListenBegin)
ON_UPDATE_COMMAND_UI(IDM_LISTEN_END, OnUpdateListenEnd)
ON_COMMAND(IDM_LISTEN_TCP, OnListenTcp)
ON_UPDATE_COMMAND_UI(IDM_LISTEN_TCP, OnUpdateListenTcp)
ON_COMMAND(IDM_LISTEN_UDP, OnListenUdp)
ON_UPDATE_COMMAND_UI(IDM_LISTEN_UDP, OnUpdateListenUdp)
ON_COMMAND(IDM_LISTEN_ICMP, OnListenIcmp)
ON_UPDATE_COMMAND_UI(IDM_LISTEN_ICMP, OnUpdateListenIcmp)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMainDoc construction/destruction

CMainDoc::CMainDoc()
{
// TODO: add one-time construction code here
DataInit();
}

CMainDoc::~CMainDoc()
{
DataUnInit();
}

BOOL CMainDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;

// TODO: add reinitialization code here
// (SDI documents will reuse this document)

return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
// CMainDoc serialization

void CMainDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// TODO: add storing code here
}
else
{
// TODO: add loading code here
}
}

/////////////////////////////////////////////////////////////////////////////
// CMainDoc diagnostics

#ifdef _DEBUG
void CMainDoc::AssertValid() const
{
CDocument::AssertValid();
}

void CMainDoc::Dump(CDumpContext& dc) const
{
CDocument::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CMainDoc commands
void CMainDoc::DataInit() {
WORD wVersionRequested;
WSADATA wsaData;
int err;

wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
/* Tell the user that we could not find a usable */
/* WinSock DLL.                                  */
return;
}

/* Confirm that the WinSock DLL supports 2.2.*/
/* Note that if the DLL supports versions greater    */
/* than 2.2 in addition to 2.2, it will still return */
/* 2.2 in wVersion since that is the version we      */
/* requested.                                        */

if (LOBYTE(wsaData.wVersion) != 2 ||
HIBYTE(wsaData.wVersion) != 2) {
/* Tell the user that we could not find a usable */
/* WinSock DLL.                                  */
WSACleanup();
return;
}

SetListenOptTCP(TRUE);
SetListenOptUDP(TRUE);
SetListenOptICMP(TRUE);
}

void CMainDoc::DataUnInit() {
WSACleanup();
}

void CMainDoc::ShowErrMsg(int iErrSn) {
LPVOID lpMsgBuf = NULL;

FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
iErrSn,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL);

if (NULL != lpMsgBuf) {
ShowThreadMsg((LPTSTR)lpMsgBuf, eImageIndex_error);
}

LocalFree(lpMsgBuf);
}

void CMainDoc::LockMsg() {
g_csDispMsg.Lock();
}

void CMainDoc::UnLockMsg() {
g_csDispMsg.UnLock();
}

list<CListRowData>& CMainDoc::GetListRowData() {
return m_ListRowData;
}

void CMainDoc::ShowThreadMsg(TCHAR* pMsg, eImageIndex ImageIndex) {
CListRowData RowData;

if (NULL != pMsg) {
RowData.m_ImageIndex = ImageIndex;
RowData.m_strDesc = pMsg;
ShowThreadMsgRowData(&RowData);
}
}

void CMainDoc::ShowThreadMsgRowData(CListRowData* pRowData) {
CWnd* pMainWnd = NULL;

if (NULL != pRowData) {
LockMsg();
GetListRowData().push_back(*pRowData);
UnLockMsg();

pMainWnd = AfxGetMainWnd();
if (NULL != pMainWnd) {
pMainWnd->PostMessage(WM_MY_UPDATE_VIEW, 0, 0);
}
}
}

void CMainDoc::ShowSocketErrMsg() {
int iErrSn = WSAGetLastError();
ShowErrMsg(iErrSn);
}

void CMainDoc::ShowErrMsg() {
int iErrSn = GetLastError();
ShowErrMsg(iErrSn);
}

void CMainDoc::OnListenBegin()
{
StartListenThread();
}

void CMainDoc::OnListenEnd()
{
StopListenThread();
}

void CMainDoc::StartListenThread() {
if (!IsThreadRunning()) {
m_ThreadNetDataListen.SetParam(
&CMainDoc::ThreadProcNetDataListen, NULL, NULL, this);
m_ThreadNetDataListen.Start();
}
}

void CMainDoc::StopListenThread() {
if (IsThreadRunning()) {
m_ThreadNetDataListen.Stop();
}
}

void CMainDoc::OnUpdateListenBegin(CCmdUI* pCmdUI)
{
BOOL bThreadIsRunning = IsThreadRunning();
pCmdUI->Enable(!bThreadIsRunning);
pCmdUI->SetCheck(bThreadIsRunning);
}

void CMainDoc::OnUpdateListenEnd(CCmdUI* pCmdUI)
{
BOOL bThreadIsRunning = IsThreadRunning();
pCmdUI->Enable(bThreadIsRunning);
pCmdUI->SetCheck(!bThreadIsRunning);
}

BOOL CMainDoc::IsThreadRunning() {
return m_ThreadNetDataListen.IsRunning();
}

unsigned __stdcall CMainDoc::ThreadProcNetDataListen(void* pParam) {
if (NULL == pParam) {
return S_FALSE;
}

return ((CMainDoc*)pParam)->ThreadProcNetDataListen();
}

unsigned CMainDoc::ThreadProcNetDataListen() {
UINT uRc = S_FALSE;
ShowThreadMsg(_T(">> 网络数据监听线程开始运行"), eImageIndex_information);
uRc = fnThreadProcNetDataListen(m_ThreadNetDataListen);
ShowThreadMsg(_T("<< 网络数据监听线程结束运行"), eImageIndex_information);
return uRc;
}

unsigned CMainDoc::fnThreadProcNetDataListen(CMyThread& Thread) {
SOCKET s = INVALID_SOCKET;
sockaddr_in addr;
int iRc = SOCKET_ERROR;
ULONG ul = 0;
char cBuf[MAXBYTE] = {'\0'};
struct hostent* pHost = NULL;
BYTE cRecvBuf[0x2000] = {'\0'};

do {
init_data_net_data_header();

s = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
if (INVALID_SOCKET == s) {
ShowSocketErrMsg();
break;
}

iRc = gethostname(cBuf, sizeof(cBuf));
if (SOCKET_ERROR == iRc) {
ShowSocketErrMsg();
break;
}

pHost = gethostbyname(cBuf);
if (NULL == pHost) {
ShowSocketErrMsg();
break;
}

addr.sin_family = AF_INET;
addr.sin_port = htons(0);
addr.sin_addr.s_addr = *((ULONG*)pHost->h_addr_list[0]);
iRc = bind(s, (struct sockaddr*)&addr, sizeof(addr));
if (SOCKET_ERROR == iRc) {
ShowSocketErrMsg();
break;
}

ul = 1;
iRc = ioctlsocket(s, SIO_RCVALL, &ul);
if (SOCKET_ERROR == iRc) {
ShowSocketErrMsg();
break;
}

do {
if (!Thread.cbIsCanContinue()) {
continue;
}

if (Thread.cbIsNeedQuit()) {
break;
}

iRc = recv(s, (char*)cRecvBuf, sizeof(cRecvBuf), 0);
if (SOCKET_ERROR == iRc) {
continue;
}

/// 分析
fnNetworkProtocolAnalysis(cRecvBuf, iRc);
} while (1);
} while (0);

if (INVALID_SOCKET != s) {
closesocket(s);
}

return S_OK;
}

BOOL CMainDoc::fnNetworkProtocolAnalysis(BYTE* pBuf, int iLenRecv) {
int iLenIpHeader = 0;
IPHDR* pIpHeader = NULL;
BYTE* pBufNow = NULL;
TAG_PROTOCOL_NAME protocolName;
CListRowData RowData;

if (NULL == pBuf) {
return FALSE;
}

if (iLenRecv < sizeof(IPHDR)) {
return FALSE;
}

pIpHeader = (IPHDR*)pBuf;
/// IP头是变长的, 有可能不是20Bytes, 要根据pIpHeader->hlen去算
iLenIpHeader = sizeof(IPHDR);
if (pIpHeader->h_len > 0) {
iLenIpHeader = pIpHeader->h_len * 4;
}

if (iLenRecv < iLenIpHeader) {
return FALSE;
}

pBufNow = (BYTE*)(pIpHeader) + iLenIpHeader;

GetProtocolName(pIpHeader->Protocol, protocolName);
RowData.m_strProtocol = protocolName.cName;

RowData.m_strSrcIp = inet_ntoa(pIpHeader->iaSrc);
RowData.m_strDstIp = inet_ntoa(pIpHeader->iaDst);
RowData.m_strDataLen.Format("%u", ntohs(pIpHeader->TotLen));

switch (pIpHeader->Protocol) {
case eProtocalIndex_TCP:
if (GetListenOptTCP()) {
fnNetworkProtocolAnalysis_TCP(iLenRecv, &RowData, pIpHeader, pBufNow, iLenRecv - iLenIpHeader);
}
break;

case eProtocalIndex_UDP:
if (GetListenOptUDP()) {
fnNetworkProtocolAnalysis_UDP(iLenRecv, &RowData, pIpHeader, pBufNow, iLenRecv - iLenIpHeader);
}
break;

case eProtocalIndex_ICMP:
if (GetListenOptICMP()) {
fnNetworkProtocolAnalysis_ICMP(iLenRecv, &RowData, pIpHeader, pBufNow, iLenRecv - iLenIpHeader);
}
break;

default:
break;
}

return TRUE;
}

BOOL CMainDoc::fnNetworkProtocolAnalysis_TCP(int iLenRecv, CListRowData* pRowData, IPHDR* pIpHeader, BYTE* pBuf, int iLenBuf) {
TCP_HEADER* pTcpHeader = NULL;
int iLenIpHeader = sizeof(IPHDR);
int iLenTcpHeader = sizeof(TCP_HEADER);
BYTE* pData = NULL;
int iLenDat = 0;

if ((NULL == pRowData) || (NULL == pIpHeader) || (NULL == pBuf) || (iLenBuf < iLenTcpHeader)) {
return FALSE;
}

if (pIpHeader->h_len > 0) {
iLenIpHeader = pIpHeader->h_len * 4;
}

pTcpHeader = (TCP_HEADER*)pBuf;
if (pTcpHeader->nHLenAndFlag > 0) {
iLenTcpHeader = ntohs(pTcpHeader->nHLenAndFlag);
iLenTcpHeader = (iLenTcpHeader >> 12) & 0x0f;
iLenTcpHeader *= 4;
}

pData = (BYTE*)pTcpHeader + iLenTcpHeader;
iLenDat = iLenBuf - iLenTcpHeader;

pRowData->m_strDataLen.Format("%d", iLenDat);

pRowData->m_strSrcIp.Format("%s:%d", inet_ntoa(pIpHeader->iaSrc), pTcpHeader->nSourPort);
pRowData->m_strDstIp.Format("%s:%d", inet_ntoa(pIpHeader->iaDst), pTcpHeader->nDestPort);

if (pIpHeader->h_len > 0) {
iLenIpHeader = pIpHeader->h_len * 4;
}

pRowData->m_strDesc.Format("[Recv:%u]"
" - IP[TotLen:%u][Len:%u][IpV%d][ID:0x%X][TTL:%d][Checksum:0x%X]"
" - TCP[Len:%u][seq:0x%X][ack:0x%X][窗口大小:0x%X][CheckSum:0x%X]",

iLenRecv,

ntohs(pIpHeader->TotLen),
iLenIpHeader,
pIpHeader->version,
ntohs(pIpHeader->ID),
pIpHeader->TTL,
ntohs(pIpHeader->Checksum),

iLenTcpHeader,
ntohl(pTcpHeader->nSequNum),
ntohl(pTcpHeader->nAcknowledgeNum),
ntohs(pTcpHeader->nWindowSize),
ntohs(pTcpHeader->nCheckSum));

fnNetworkProtocolAnalysis_AddData(iLenRecv, pRowData, pData, iLenDat);

return TRUE;
}

BOOL CMainDoc::fnNetworkProtocolAnalysis_UDP(int iLenRecv, CListRowData* pRowData, IPHDR* pIpHeader, BYTE* pBuf, int iLenBuf) {
UDP_HEADER* pUdpHeader = NULL;
int iLenIpHeader = sizeof(IPHDR);
int iLenUdpHeader = sizeof(UDP_HEADER);
BYTE* pData = NULL;
int iLenDat = 0;

if ((NULL == pRowData) || (NULL == pIpHeader) || (NULL == pBuf) || (iLenBuf < iLenUdpHeader)) {
return FALSE;
}

pUdpHeader = (UDP_HEADER*)pBuf;
pData = (BYTE*)(pUdpHeader + 1);
iLenDat = iLenBuf - iLenUdpHeader;

pRowData->m_strDataLen.Format("%d", iLenDat);

pRowData->m_strSrcIp.Format("%s:%d", inet_ntoa(pIpHeader->iaSrc), pUdpHeader->nSourPort);
pRowData->m_strDstIp.Format("%s:%d", inet_ntoa(pIpHeader->iaDst), pUdpHeader->nDestPort);

if (pIpHeader->h_len > 0) {
iLenIpHeader = pIpHeader->h_len * 4;
}

pRowData->m_strDesc.Format("[Recv:%u]"
" - IP[TotLen:%u][Len:%u][IpV%d][ID:0x%X][TTL:%d][Checksum:0x%X]"
" - UDP[TotLen:%u][Len:%u][CheckSum:0x%X]",

iLenRecv,

ntohs(pIpHeader->TotLen),
iLenIpHeader,
pIpHeader->version,
ntohs(pIpHeader->ID),
pIpHeader->TTL,
ntohs(pIpHeader->Checksum),

ntohs(pUdpHeader->nLength),
iLenUdpHeader,
ntohs(pUdpHeader->nCheckSum));

fnNetworkProtocolAnalysis_AddData(iLenRecv, pRowData, pData, iLenDat);

return TRUE;
}

BOOL CMainDoc::fnNetworkProtocolAnalysis_ICMP(int iLenRecv, CListRowData* pRowData, IPHDR* pIpHeader, BYTE* pBuf, int iLenBuf) {
ICMPHDR* pIcmpHeader = NULL;
int iLenIpHeader = sizeof(IPHDR);
int iLenIcmpHeader = sizeof(ICMPHDR) - 1; ///< 不算柔性数组的开始字节
BYTE* pData = NULL;
int iLenDat = 0;

if ((NULL == pRowData) || (NULL == pIpHeader) || (NULL == pBuf) || (iLenBuf < iLenIcmpHeader)) {
return FALSE;
}

pIcmpHeader = (ICMPHDR*)pBuf;
pData = (BYTE*)(pIcmpHeader + 1) - 1; ///< 不算柔性数组的开始字节
iLenDat = iLenBuf - iLenIcmpHeader;

pRowData->m_strDataLen.Format("%d", iLenDat);

if (pIpHeader->h_len > 0) {
iLenIpHeader = pIpHeader->h_len * 4;
}

pRowData->m_strDesc.Format("[Recv:%u]"
" - IP[TotLen:%u][Len:%u][IpV%d][ID:0x%X][TTL:%d][Checksum:0x%X]"
" - ICMP[Len:%u][Type:%u][Code:%u][CheckSum:0x%X]",

iLenRecv,

ntohs(pIpHeader->TotLen),
iLenIpHeader,
pIpHeader->version,
ntohs(pIpHeader->ID),
pIpHeader->TTL,
ntohs(pIpHeader->Checksum),

iLenIcmpHeader,
pIcmpHeader->Type,
pIcmpHeader->Code,
ntohs(pIcmpHeader->Checksum));

fnNetworkProtocolAnalysis_AddData(iLenRecv, pRowData, pData, iLenDat);

return TRUE;
}

BOOL CMainDoc::fnNetworkProtocolAnalysis_AddData(int iLenRecv, CListRowData* pRowData, BYTE* pBuf, int iLenBuf) {
BOOL bFirstAddMsg = TRUE;
int i = 0;

/// ListView中的ListCtrl, 一列现实不了那么多, 就(80~90)*3那么多Ascii字符
const int iMaxShowBytes = 16;
int iProcessCnt = 0;
CString str;

if ((NULL == pRowData) || (NULL == pBuf) || (iLenBuf < 0)) {
return FALSE;
}

pRowData->m_strDataContent.Empty();
for (i = 0; i < iLenBuf; i++) {
str.Format(_T("%02X "), pBuf[i]);
pRowData->m_strDataContent += (LPTSTR)(LPCTSTR)str;
if (iProcessCnt < (iMaxShowBytes - 1)) {
iProcessCnt++;
} else {
if (bFirstAddMsg) {
bFirstAddMsg = FALSE;
pRowData->m_ImageIndex = eImageIndex_information;
} else {
pRowData->m_ImageIndex = eImageIndex_null;
}
ShowThreadMsgRowData(pRowData);
pRowData->Clear();
iProcessCnt = 0;
}
}

if (iProcessCnt > 0) {
if (bFirstAddMsg) {
bFirstAddMsg = FALSE;
pRowData->m_ImageIndex = eImageIndex_information;
} else {
pRowData->m_ImageIndex = eImageIndex_null;
}
ShowThreadMsgRowData(pRowData);
pRowData->Clear();
}

return TRUE;
}

void CMainDoc::OnListenTcp()
{
SetListenOptTCP(!GetListenOptTCP());
}

void CMainDoc::OnUpdateListenTcp(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(GetListenOptTCP());
}

void CMainDoc::OnListenUdp()
{
SetListenOptUDP(!GetListenOptUDP());
}

void CMainDoc::OnUpdateListenUdp(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(GetListenOptUDP());
}

void CMainDoc::OnListenIcmp()
{
SetListenOptICMP(!GetListenOptICMP());
}

void CMainDoc::OnUpdateListenIcmp(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(GetListenOptICMP());
}

void CMainDoc::SetListenOptTCP(BOOL bParam) {
m_bListernTCP = bParam;
}

BOOL CMainDoc::GetListenOptTCP() {
return m_bListernTCP;
}

void CMainDoc::SetListenOptUDP(BOOL bParam) {
m_bListernUDP = bParam;
}

BOOL CMainDoc::GetListenOptUDP() {
return m_bListernUDP;
}

void CMainDoc::SetListenOptICMP(BOOL bParam) {
m_bListernICMP = bParam;
}

BOOL CMainDoc::GetListenOptICMP() {
return m_bListernICMP;
}


// MainView.h : interface of the CMainView class
//
/////////////////////////////////////////////////////////////////////////////

#if !defined(AFX_MAINVIEW_H__A45AF28F_5CC6_43A0_912C_90AF75F7CA75__INCLUDED_)
#define AFX_MAINVIEW_H__A45AF28F_5CC6_43A0_912C_90AF75F7CA75__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "ListRowData.h"

class CMainView : public CListView
{
protected: // create from serialization only
CMainView();
DECLARE_DYNCREATE(CMainView)

// Attributes
public:
CMainDoc* GetDocument();

// Operations
public:

// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CMainView)
public:
virtual void OnDraw(CDC* pDC);  // overridden to draw this view
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual void OnInitialUpdate(); // called first time after construct
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint);
//}}AFX_VIRTUAL

// Implementation
public:
virtual ~CMainView();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif

protected:

// Generated message map functions
protected:
//{{AFX_MSG(CMainView)
afx_msg void OnRclick(NMHDR* pNMHDR, LRESULT* pResult);
afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
afx_msg void OnListenContentClear();
afx_msg void OnTimer(UINT nIDEvent);
afx_msg void OnDestroy();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()

public:
void ShowUiMsg(TCHAR* pcMsg);
void ShowUiMsg(CListRowData* pRowData);

private:
void AddRowToUI(CListRowData* pListRowData);
void AdjustColWidth();
void MyUpdateUI();

private:
CImageList m_ImageList; ///< 图像列表, 用于调整行高
BOOL m_bListViewInitOk; ///< 视图是否已经初始化过?
};

#ifndef _DEBUG  // debug version in MainView.cpp
inline CMainDoc* CMainView::GetDocument()
{ return (CMainDoc*)m_pDocument; }
#endif

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_MAINVIEW_H__A45AF28F_5CC6_43A0_912C_90AF75F7CA75__INCLUDED_)


// MainView.cpp : implementation of the CMainView class
//

#include "stdafx.h"
#include "NetDataViewer.h"

#include "MainDoc.h"
#include "MainView.h"

#include "ListRowData.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define TIMER_EVENT_SN_ON_UPDATE 1
#define TIMER_DELAY_ON_UPDATE 500

/////////////////////////////////////////////////////////////////////////////
// CMainView

IMPLEMENT_DYNCREATE(CMainView, CListView)

BEGIN_MESSAGE_MAP(CMainView, CListView)
//{{AFX_MSG_MAP(CMainView)
ON_NOTIFY_REFLECT(NM_RCLICK, OnRclick)
ON_WM_RBUTTONDOWN()
ON_COMMAND(IDM_LISTEN_CONTENT_CLEAR, OnListenContentClear)
ON_WM_TIMER()
ON_WM_DESTROY()
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CListView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CListView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CListView::OnFilePrintPreview)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMainView construction/destruction

CMainView::CMainView()
{
m_bListViewInitOk = FALSE;
}

CMainView::~CMainView()
{
}

BOOL CMainView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
//  the CREATESTRUCT cs

return CListView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CMainView drawing

void CMainView::OnDraw(CDC* pDC)
{
CMainDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
}

void CMainView::AdjustColWidth() {
int i = 0;
int iArySize = sizeof(g_ListColumnName) / sizeof(g_ListColumnName[0]);
CListCtrl& theCtrl = GetListCtrl();

for (i = 0; i < iArySize; i++) {
theCtrl.SetColumnWidth(i, LVSCW_AUTOSIZE_USEHEADER);
}
}

void CMainView::OnInitialUpdate()
{
DWORD dwStyleEx = LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES /*| LVS_EX_FLATSB*/;
int i = 0;
int iArySize = sizeof(g_ListColumnName) / sizeof(g_ListColumnName[0]);
LVCOLUMN col;

CListView::OnInitialUpdate();
CListCtrl& theCtrl = GetListCtrl();

m_ImageList.Create(16, 16, ILC_MASK | ILC_COLOR32, 0, 1); ///< 可以依靠图像size来调整行高

m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_IMAGE_NULL));
m_ImageList.Add(::LoadIcon(NULL, IDI_INFORMATION));
m_ImageList.Add(::LoadIcon(NULL, IDI_WARNING));
m_ImageList.Add(::LoadIcon(NULL, IDI_ERROR));

ASSERT(theCtrl.GetImageList(LVSIL_SMALL) == NULL);
theCtrl.SetImageList(&m_ImageList, LVSIL_SMALL);
ASSERT(theCtrl.GetImageList(LVSIL_SMALL) == &m_ImageList);

// TODO: You may populate your ListView with items by directly accessing
//  its list control through a call to GetListCtrl().
// this code only works for a report-mode list view
ModifyStyle(0, LVS_REPORT, 0);
ASSERT(GetStyle() & LVS_REPORT);

CListView::OnInitialUpdate();

// Gain a reference to the list control itself
theCtrl.SetExtendedStyle
(theCtrl.GetExtendedStyle() | dwStyleEx);

for (i = 0; i < iArySize; i++) {
col.mask = LVCF_FMT | LVCF_TEXT;
col.pszText = (char*)g_ListColumnName[i];
col.fmt = LVCFMT_LEFT;
theCtrl.InsertColumn(i, &col);
theCtrl.SetColumnWidth(i, LVSCW_AUTOSIZE_USEHEADER);
}

/// 设置题头的自动列宽,要在列插入完成后,再设置
AdjustColWidth();

m_bListViewInitOk = TRUE;
GetDocument()->ShowThreadMsg(_T("请执行网络包的检测[可以选择主菜单, 工具条, 右键菜单]"), eImageIndex_information);

SetTimer(TIMER_EVENT_SN_ON_UPDATE, TIMER_DELAY_ON_UPDATE, NULL);
}

/////////////////////////////////////////////////////////////////////////////
// CMainView printing

BOOL CMainView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}

void CMainView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}

void CMainView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}

/////////////////////////////////////////////////////////////////////////////
// CMainView diagnostics

#ifdef _DEBUG
void CMainView::AssertValid() const
{
CListView::AssertValid();
}

void CMainView::Dump(CDumpContext& dc) const
{
CListView::Dump(dc);
}

CMainDoc* CMainView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMainDoc)));
return (CMainDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CMainView message handlers
void CMainView::ShowUiMsg(TCHAR* pcMsg) {
int iRc = 0;
CListRowData RowData;

if (NULL != pcMsg) {
RowData.m_strDesc = pcMsg;
AddRowToUI(&RowData);
}
}

void CMainView::ShowUiMsg(CListRowData* pRowData) {
if (NULL != pRowData) {
AddRowToUI(pRowData);
}
}

void CMainView::AddRowToUI(CListRowData* pListRowData) {
int i = 0;
int iArySize = sizeof(g_ListColumnName) / sizeof(g_ListColumnName[0]);
CListCtrl& theCtrl = GetListCtrl();
int iRowCnt = theCtrl.GetItemCount();
LVITEM lvitem;
int iColIndex = 0;

if (NULL != pListRowData) {
lvitem.mask = LVIF_TEXT | LVIF_IMAGE;
lvitem.iImage = pListRowData->m_ImageIndex;

lvitem.iItem = iRowCnt;
lvitem.iSubItem = iColIndex++;

lvitem.pszText = _T("");
theCtrl.InsertItem(&lvitem);

theCtrl.SetItemText(iRowCnt, iColIndex++, (LPTSTR)(LPCTSTR)pListRowData->m_strProtocol);
theCtrl.SetItemText(iRowCnt, iColIndex++, (LPTSTR)(LPCTSTR)pListRowData->m_strSrcIp);
theCtrl.SetItemText(iRowCnt, iColIndex++, (LPTSTR)(LPCTSTR)pListRowData->m_strDstIp);
theCtrl.SetItemText(iRowCnt, iColIndex++, (LPTSTR)(LPCTSTR)pListRowData->m_strDesc);
theCtrl.SetItemText(iRowCnt, iColIndex++, (LPTSTR)(LPCTSTR)pListRowData->m_strDataLen);
theCtrl.SetItemText(iRowCnt, iColIndex++, (LPTSTR)(LPCTSTR)pListRowData->m_strDataContent);
}
}

void CMainView::OnListenContentClear()
{
CListCtrl& theCtrl = GetListCtrl();

GetDocument()->LockMsg();
theCtrl.DeleteAllItems();
if (!GetDocument()->GetListRowData().empty()) {
GetDocument()->GetListRowData().clear();
}
GetDocument()->UnLockMsg();
}

void CMainView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
{
MyUpdateUI();
}

void CMainView::MyUpdateUI() {
CString str;
CListRowData RowData;
BOOL bHaveData = FALSE;

/// 防止UI显示数据太猛挂掉
int iCntWasDisplay = 0; ///< 在这个更新显示中,已经显示了多少条数据
const int iCntWasDisplayMax = 60; ///< 最多显示多少条就跳出,等待下一次来显示

if (m_bListViewInitOk) {
do {
bHaveData = FALSE;

/// 不能阻塞那么长时间, 只拿一条数据,就让出临界区
GetDocument()->LockMsg();
if (!GetDocument()->GetListRowData().empty()) {
bHaveData = TRUE;
RowData = GetDocument()->GetListRowData().front();
GetDocument()->GetListRowData().pop_front();
}
GetDocument()->UnLockMsg();

if (bHaveData) {
ShowUiMsg(&RowData);
iCntWasDisplay++;
}
} while (bHaveData && (iCntWasDisplay < iCntWasDisplayMax));

/// 将所有数据都取光,再一次性调整列宽为自动, 防止数据多了,UI挂掉
AdjustColWidth();
}
}

void CMainView::OnRclick(NMHDR* pNMHDR, LRESULT* pResult)
{
// TODO: Add your control notification handler code here

*pResult = 0;
}

void CMainView::OnRButtonDown(UINT nFlags, CPoint point)
{
CMenu menu;
CMenu* pSubMenu = NULL;
BOOL bThreadIsRunning = GetDocument()->IsThreadRunning();

CListView::OnRButtonDown(nFlags, point);

ClientToScreen(&point);
menu.LoadMenu(MAKEINTRESOURCE(IDR_MENU_LIST_VIEW));
pSubMenu = menu.GetSubMenu(0);

pSubMenu->CheckMenuItem(IDM_LISTEN_BEGIN, bThreadIsRunning ? MF_CHECKED : MF_UNCHECKED);
pSubMenu->EnableMenuItem(IDM_LISTEN_BEGIN, bThreadIsRunning ? (MF_DISABLED | MF_GRAYED) : MF_ENABLED);

pSubMenu->CheckMenuItem(IDM_LISTEN_END, !bThreadIsRunning ? MF_CHECKED : MF_UNCHECKED);
pSubMenu->EnableMenuItem(IDM_LISTEN_END, !bThreadIsRunning ? (MF_DISABLED | MF_GRAYED) : MF_ENABLED);

pSubMenu->CheckMenuItem(IDM_LISTEN_TCP, GetDocument()->GetListenOptTCP() ? MF_CHECKED : MF_UNCHECKED);
pSubMenu->CheckMenuItem(IDM_LISTEN_UDP, GetDocument()->GetListenOptUDP() ? MF_CHECKED : MF_UNCHECKED);
pSubMenu->CheckMenuItem(IDM_LISTEN_ICMP, GetDocument()->GetListenOptICMP() ? MF_CHECKED : MF_UNCHECKED);

pSubMenu->TrackPopupMenu(
TPM_LEFTALIGN |TPM_RIGHTBUTTON,
point.x, point.y, this);
}

void CMainView::OnTimer(UINT nIDEvent)
{
CListView::OnTimer(nIDEvent);

if (TIMER_EVENT_SN_ON_UPDATE == nIDEvent) {
/// 靠pDoc->UpdateAllViews来刷UI太猛了,UI挂掉了
/// 为啥只来一次?
KillTimer(TIMER_EVENT_SN_ON_UPDATE);
MyUpdateUI();
SetTimer(TIMER_EVENT_SN_ON_UPDATE, TIMER_DELAY_ON_UPDATE, NULL);
}
}

void CMainView::OnDestroy()
{
CListView::OnDestroy();

// TODO: Add your message handler code here
KillTimer(TIMER_EVENT_SN_ON_UPDATE);
}


网络包头结构定义

/// @file net_data_header.h
/// @brief 网络通讯的包头数据结构的定义
/// http://blog.csdn.net/ithomer/article/details/5662383 这个资料有全面网络包结构定义

#ifndef __NET_DATA_HEADER_H_2016_0409__
#define __NET_DATA_HEADER_H_2016_0409__

#pragma pack(push)
#pragma pack(1)

#define ICMP_ECHOREPLY  0
#define ICMP_HOST_NOTEXIST 3 ///< 主机不存在
#define ICMP_ECHOREQ    8

// https://en.wikipedia.org/wiki/List_of_IP_protocol_numbers enum eProtocalIndex {
eProtocalIndex_Reserved = 0xff,
eProtocalIndex_ICMP = 1,
eProtocalIndex_TCP = 6,
eProtocalIndex_UDP = 17,
};

// IP Header -- RFC 791
// https://en.wikipedia.org/wiki/List_of_IP_protocol_numbers 
typedef struct _tag_Protocol_name {
BYTE ucProtocol;
char cName[MAX_PATH];
}TAG_PROTOCOL_NAME;

void init_data_net_data_header();
BOOL GetProtocolName(IN BYTE cProtocol, OUT TAG_PROTOCOL_NAME& info);

typedef struct tagIPHDR
{
// u_char  VIHL;        // Version and IHL
u_char h_len:4;         // length of header
u_char version:4;       // Version of IP

u_char  TOS;            // Type Of Service
short   TotLen;         // Total Length
short   ID;             // Identification
short   FlagOff;        // Flags and Fragment Offset
u_char  TTL;            // Time To Live
u_char  Protocol;       // Protocol(tcp, udp, etc.)
u_short Checksum;       // Checksum
struct  in_addr iaSrc;  // Internet Address - Source
struct  in_addr iaDst;  // Internet Address - Destination
}IPHDR, *PIPHDR;

typedef struct _UDP_HEADER
{
USHORT nSourPort ;   // 源端口号16bit
USHORT nDestPort ;   // 目的端口号16bit
USHORT nLength ;     // 数据包长度16bit
USHORT nCheckSum ;   // 校验和16bit
}UDP_HEADER, *PUDP_HEADER;

typedef struct _TCP_HEADER
{
USHORT nSourPort; // 源端口号16bit
USHORT nDestPort; // 目的端口号16bit
UINT nSequNum; // 序列号32bit
UINT nAcknowledgeNum; // 确认号32bit

USHORT nHLenAndFlag; // (前4位:TCP头长度;中6位:保留;后6位:标志位)共16bit
/** 这样将位域分开也不行, 还是得对nHLenAndFlag移位
BYTE nTcpFlag1:4;
BYTE nTcpFlag2:2;
BYTE nTcpUnused1:2;
BYTE nTcpUnused2:4;
BYTE nTcpLen:4;
*/

USHORT nWindowSize; // 窗口大小16bit
USHORT nCheckSum; // 检验和16bit
USHORT nrgentPointer; // 紧急数据偏移量16bit
}TCP_HEADER, *PTCP_HEADER;

// ICMP Header - RFC 792
typedef struct tagICMPHDR
{
u_char  Type;           // Type
u_char  Code;           // Code
u_short Checksum;       // Checksum

/// http://network.51cto.com/art/201007/211240_all.htm BYTE icmp_data[1];
}ICMPHDR, *PICMPHDR;

#define REQ_DATASIZE 32     // Echo Request Data size

// ICMP Echo Request
typedef struct tagECHOREQUEST
{
ICMPHDR icmpHdr;
//  DWORD   dwTime;
char    cData[REQ_DATASIZE];
}ECHOREQUEST, *PECHOREQUEST;

// ICMP Echo Reply
typedef struct tagECHOREPLY
{
IPHDR   ipHdr;
ECHOREQUEST echoRequest;
char    cFiller[256];
}ECHOREPLY, *PECHOREPLY;

#pragma pack(pop)

#endif // #ifndef __NET_DATA_HEADER_H_2016_0409__
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: