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

📄 fvenumnet.cpp

📁 枚举主机网络设备
💻 CPP
字号:
// FVEnumNet.cpp : implementation file
//

#include "stdafx.h"
#include "FVEnumNet.h"
#include "arp.h"

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

extern HINSTANCE g_hInsGJEnumNetDLL;


/////////////////////////////////////////////////////////////////////////////
// CFVEnumNet

IMPLEMENT_DYNCREATE(CFVEnumNet, CFormView)

CFVEnumNet::CFVEnumNet(CString strDllFile)
	: CFormView(CFVEnumNet::IDD),m_strDllFile(strDllFile)
{
	//{{AFX_DATA_INIT(CFVEnumNet)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
}

CFVEnumNet::~CFVEnumNet()
{
}

void CFVEnumNet::DoDataExchange(CDataExchange* pDX)
{
	CFormView::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CFVEnumNet)
	DDX_Control(pDX, IDC_STATIC_FUNCTION, m_oHsTitle);
	DDX_Control(pDX, IDC_STATIC_XBK, m_oHGif);
	DDX_Control(pDX, IDC_TREE, m_oTree);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CFVEnumNet, CFormView)
	//{{AFX_MSG_MAP(CFVEnumNet)
	ON_WM_SIZE()
	//}}AFX_MSG_MAP
	ON_MESSAGE(UM_ENUM_NET, OnEnumNet)
	ON_MESSAGE(UM_CLK_TREE_ITEM, OnTreeItemChanged)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CFVEnumNet diagnostics

#ifdef _DEBUG
void CFVEnumNet::AssertValid() const
{
	CFormView::AssertValid();
}

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

/////////////////////////////////////////////////////////////////////////////
// CFVEnumNet message handlers

void CFVEnumNet::OnInitialUpdate() 
{
	CFormView::OnInitialUpdate();
	
	if(m_oHGif.Load(MAKEINTRESOURCE(IDR_EARTH),"GIF",g_hInsGJEnumNetDLL)){
		m_oHGif.SetBkColor(RGB(255,255,255));
		m_oHGif.Draw();
	}

	CString strText,str;
	m_oHsTitle.GetWindowText(str);
	BOOL bFromNet=(m_strDllFile.Find(STR_XBKR_PROTOCAL_HEAD,0)>=0);
	strText.Format(" %s(%s版)",str,(bFromNet?"网络":"单机"));
	strText+="																																";
	strText+="																																";
	m_oHsTitle.SetWindowText(strText);
	m_oHsTitle.SetFontColor(RGB(255,255,255));
	m_oHsTitle.SetFontHeight(25);
	m_oHsTitle.SetFontWeight(400);
	m_oHsTitle.SetBkColor(GetSysColor(COLOR_3DDKSHADOW));
	m_oHsTitle.SetWindowPos(NULL,40,8,1800,26,SWP_SHOWWINDOW);

	EnumNetCard();
}

int CFVEnumNet::EnumNetCard() 
{
	HTREEITEM hRoot=m_oTree.InsertItem("网络适配器");
	m_oTree.SetItemData(hRoot,ITEM_DATA_ROOT);

	pcap_if_t *alldevs=NULL; 
	pcap_if_t *pDvc=NULL;
	pcap_addr_t *pAdr=NULL;
	char szErr[PCAP_ERRBUF_SIZE+1];
	if(-1==pcap_findalldevs(&alldevs,szErr)){// 取设备列表 
		AfxPromptBox(szErr);
		return -1;
	}

	int nCount=0;
	CString str;
	pDvc=alldevs;
	while(NULL!=pDvc){
		if(NULL==pDvc->description){
			pDvc=pDvc->next;
			continue;
		}
		nCount++;
		str=pDvc->description;
		str.TrimRight();
		HTREEITEM hItem=m_oTree.InsertItem(str,hRoot);
		m_oTree.SetItemData(hItem,ITEM_DATA_CARD);


		while(1){
			pAdr=pDvc->addresses;
			if(NULL==pAdr){
				str="没有地址";
				break;
			}

			if(AF_INET!=pAdr->addr->sa_family){
				str="不是IP地址类型";
				break;
			}

			DWORD dwLocalIP=((struct sockaddr_in *)pAdr->addr)->sin_addr.s_addr;

			if('0'==ipTostr(dwLocalIP)[0]){
				str="该适配器连接不正常";
				break;
			}

			if(!g_gotMac){
				g_chLocalMac=getSelfMac(pDvc->name,dwLocalIP);
			}
			if(!g_gotMac){
				str="该适配器工作不正常";
				break;
			}
		
			str.Format("%s[NetMask:%s](单击查找此局网内的活动主机)",ipTostr(dwLocalIP),
				ipTostr(((struct sockaddr_in *)pAdr->netmask)->sin_addr.s_addr));
			break;
		}

		HTREEITEM h=m_oTree.InsertItem(str,hItem);
		m_oTree.SetItemData(h,ITEM_DATA_DOMAIN);

		pDvc=pDvc->next;
	}

	pcap_freealldevs(alldevs);
	
	return nCount;
}

void CFVEnumNet::SetControlPos() 
{
	CRect rc,rcTree,rcBnEnum;
	GetClientRect(&rc);
	int nH=rc.Height();
	int nW=rc.Width();

	rcTree=rc;
	rcTree.top+=45;
	rcTree.bottom-=3;
	if(m_oTree.GetSafeHwnd()!=NULL)
		m_oTree.MoveWindow(rcTree);
}

void CFVEnumNet::OnSize(UINT nType, int cx, int cy) 
{
	CFormView::OnSize(nType, cx, cy);
	
	SetControlPos();
}

LRESULT CFVEnumNet::OnTreeItemChanged(WPARAM wParam, LPARAM lParam)
{
	if(ITEM_DATA_DOMAIN!=wParam)return 0;
	CTreeItemSelChangedParm p=*(CTreeItemSelChangedParm*)lParam;

	CString str=p.m_strPath;
	CString strDvc=AnalysisAddress(str);
	str.Replace(strDvc,"");
	str.TrimLeft('\\');
	strDvc=AnalysisAddress(str);

	pcap_if_t* alldevs = 0; 
	pcap_if_t* pDvc = 0;
	pcap_addr_t* pAdr = 0;
	char szErr[PCAP_ERRBUF_SIZE + 1]; 
	if(-1==pcap_findalldevs(&alldevs,szErr)){// 取设备列表 
		AfxPromptBox(szErr);
		return -1;
	}

	pDvc=alldevs;
	while(NULL!=pDvc){
		if(NULL==pDvc->description){
			pDvc=pDvc->next;
			continue;
		}
		str=pDvc->description;
		str.TrimRight();
		if(str==strDvc)break;
		pDvc=pDvc->next;
	}
	if(NULL==pDvc)return 0;
	
	SQueryParam qp;
	qp.pDvc=pDvc;
	qp.hItem=p.m_hItem;
	qp.pWnd=this;
	g_bThreadWaitingStop=0;
	AfxBeginThread(ThreadWaiting,&qp);
	MessageLoop();//交出CPU,线程完成初始化
	AfxBeginThread(ThreadQuery,pDvc);
	
	return 1;
}

UINT CFVEnumNet::ThreadQuery(LPVOID lParam)
{
	//对选中设备的所有绑定的IP网段进行ARP请求
	sendArpReq((pcap_if_t*)lParam,g_chLocalMac);
	return 0;
}

UINT CFVEnumNet::ThreadWaiting(LPVOID lParam)
{
	SQueryParam qp;
	qp.pWnd=((SQueryParam*)lParam)->pWnd;
	qp.hItem=((SQueryParam*)lParam)->hItem;
	qp.pDvc=((SQueryParam*)lParam)->pDvc;

	char szErr[PCAP_ERRBUF_SIZE+1]; 

	//arp包最大长度是60,节省内存资源,不设为65536!并且只接收发往本机的ARP包,
	//由过滤器与非混杂模式两个条件决定
	pcap_t *pAdaptHandle=pcap_open_live(qp.pDvc->name,60,0,100,szErr);
	if (NULL==pAdaptHandle){
		CHGeneric::AfxPromptBox("无法打开适配器,可能与之不兼容!\n%s",szErr);
		return -1;
	}
	string ipWithMac[BUFFERSIZE];
	bpf_program fcode;
	usint arp_op = 0;
	uchar* arp_sha = (uchar*)malloc(sizeof(uchar) * 6);
	ulint arp_spa = 0;
	struct pcap_pkthdr *header;
	const u_char *pkt_data;

	//这里可以加大过滤范围,因为本程序工作在共享介质的网内,不会太大
	char* szFilter = "arp";//"ether proto\\arp";
	if (pcap_compile(pAdaptHandle, &fcode, szFilter, 1, (ulint)(0xFFFFFF)) < 0){
		AfxPromptBox("过滤条件语法错误!");
		free(arp_sha);
		return -1;
	}
	//设置过滤条件
	if (pcap_setfilter(pAdaptHandle, &fcode) < 0){
		AfxPromptBox("适配器与过滤条件不兼容!");
		free(arp_sha);
		return -1;
	}

	int nIdx = 0;
	while(1){
		if (g_bThreadWaitingStop) break;
		if (0==pcap_next_ex(pAdaptHandle,&header,&pkt_data))continue;//空包,继续收一下包
		
		ipWithMac[nIdx] = "";
		memcpy(&arp_op, pkt_data + 20, 2);
		memcpy(arp_sha, pkt_data + 22, 6);
		memcpy(&arp_spa, pkt_data + 28, 4);

		ipWithMac[nIdx] += ipTostr(arp_spa);
		ipWithMac[nIdx] += "[MAC:";
		ipWithMac[nIdx] += macTostr(arp_sha);
		ipWithMac[nIdx] += "]";

		//前三位是厂商ID,通常一个网络小环境买的网卡大多出自一厂,
		for (int i = 5; i >= 0; i--){
			if (arp_sha[i] != g_chLocalMac[i])break;
		}
		if(arp_op == htons(ARP_REPLY) && i + 1){
			if (BUFFERSIZE==nIdx)nIdx=0;
			if(NULL==qp.pWnd)break;
			qp.pWnd->PostMessage(UM_ENUM_NET,0,
					LPARAM(new CTreeItemSelChangedParm(qp.hItem,ITEM_DATA_DOMAIN,
					((string)ipWithMac[nIdx]).c_str())));
		}
	}
	free(arp_sha);
	return 0;
}

LRESULT CFVEnumNet::OnEnumNet(WPARAM wParam, LPARAM lParam)
{
	if(NULL==lParam)return 0;

	CTreeItemSelChangedParm p=*(CTreeItemSelChangedParm*)lParam;

	if(NULL!=m_oTree.GetChildItemByText(p.m_hItem,p.m_strPath))return 0;
	m_oTree.InsertItem(p.m_strPath,p.m_hItem);
	m_oTree.Invalidate();

	return 0;
}

⌨️ 快捷键说明

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