int XTable::Draw(CDC* pDC) { //…
if (focusRow < rows && focusCol < cols) //** {
RECT rect = GetRect (focusRow, focusCol);
GetCells (focusRow, focusCol)->DrawHitBorder(pDC, rect, RGB(0xb0, 0xb0, 0xb0)); } return 0; }
int XCell::DrawHitBorder (CDC* pDC, RECT rect, COLORREF color) {
CPen pen (PS_SOLID, 2, color);
CPen* oldPen = pDC->SelectObject(&pen); pDC->MoveTo (rect.left, rect.top); pDC->LineTo (rect.right, rect.top); pDC->LineTo (rect.right, rect.bottom); pDC->LineTo (rect.left, rect.bottom); pDC->LineTo (rect.left, rect.top); pDC->SelectObject(oldPen); return 0; }
获得IP地址监控范围内主机列表的方法如下:
m_fromip.GetAddress(fromip); m_toip.GetAddress(toip);
rthread = CreateThread(NULL, 0, sniff, 0, 0, 0); Sleep(100); //保证sniff线程已经稳定运行 SendArpReq(1, myip, mmac); while (1) {
if (!(!mmac[0] && !mmac[1] && !mmac[2] && !mmac[3])) break; Sleep(100); }
for (unsigned long i = fromip; i < myip; i++) {
SendArpReq(myip, i, mmac); }
for (i = myip + 1; i <= toip; i++) {
SendArpReq(myip, i, mmac); }
Sleep(1000);
for (i = 0; i < currentHstIndex; i++) {
HOSTENT *tmpHostent;
tmpHostent = gethostbyaddr((char*)(&(hostList[i].ip)), 16, AF_INET); if (tmpHostent)
m_hostList.SetText(i + 1, 0, tmpHostent->h_name);
m_hostList.SetText(i + 1, 1, inet_ntoa(*(struct in_addr*)(&(hostList[i].ip)))) ; m_hostList.SetText(i + 1, 3, \ CString str;
str.Format(\ hostList[i].mac[1], hostList[i].mac[2], hostList[i].mac[3], hostList[i].mac[4], hostList[i].mac[5]); m_hostList.SetText(i + 1, 2, str); m_hostList.SetText(i + 1, 4, \ m_hostList.SetText(i + 1, 5, \}
m_hostList.Invalidate();
上述代码的思路是给fromip~min(myip-1,toip),myip+1~toip范围内的主机发送ARP请求报文并监控其ARP回复,从而获得其IP与MAC的对应关系。当然,它首先用了同样的原理来获取本机的MAC地址。
为了在表格的垂直滚动条滚动时正确的设置滚动条的位置和显示正确的主机列表,我们应该给XTable添加垂直滚动条消息处理函数:
void XTable::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar *pScrollBar) {
// TODO: Add your message handler code here and/or call default static UINT nVWndPos = 0; switch (nSBCode) {
case SB_LINEDOWN: case SB_PAGEDOWN: nPos = nVWndPos + 13; SetScrollPos(SB_VERT, nPos); nVWndPos = nPos;
break;
case SB_LINEUP: case SB_PAGEUP: nPos = nVWndPos - 13; SetScrollPos(SB_VERT, nPos); nVWndPos = nPos; break;
case SB_THUMBTRACK: SetScrollPos(SB_VERT, nPos); nVWndPos = nPos; break; }
for (int i = nVWndPos / 13, j = 0; i < currentHstIndex; i++, j++) {
CString str;
SetText(j + 1, 0, inet_ntoa(*(struct in_addr*)(&(hostList[i].ip))));
if (hostList[i].sniffer == 0) SetText(j + 1, 2, \ else
SetText(j + 1, 2, \
str.Format(\ hostList[i].mac[1], hostList[i].mac[2], hostList[i].mac[3], hostList[i].mac[4], hostList[i].mac[5]); SetText(i + 1, 1, str);
if (hostList[i].arpCheat == 0) SetText(j + 1, 3, \ else
SetText(j + 1, 3, \ if (hostList[i].ipConflict == 0) SetText(j + 1, 4, \ else
SetText(j + 1, 4, \ }
for (; j < MAX_HOST; j++) {
for (int k = 0; k < 5; k++) SetText(j + 1, k, \ }
Invalidate();
CWnd::OnVScroll(nSBCode, nPos, pScrollBar); }
上述程序依赖于监控(sniffer)相关代码,核心代码如下:
DWORD WINAPI Sniff(void *p) {
char recvbuf[1024 *250];
memset(packetList, 0, MAX_PACKET *sizeof(PacketList));
if (PacketSetHwFilter(lpadapter, NDIS_PACKET_TYPE_PROMISCUOUS) == FALSE) {
AfxMessageBox(\ return - 1; }
if (PacketSetBuff(lpadapter, 500 *1024) == FALSE) {
AfxMessageBox(\ return - 1; }
if (PacketSetReadTimeout(lpadapter, 0) == FALSE) {
AfxMessageBox(\ return - 1; }
if ((lppacketr = PacketAllocatePacket()) == FALSE) {
AfxMessageBox(\ return - 1; }
PacketInitPacket(lppacketr, (char*)recvbuf, sizeof(recvbuf));
while (1) {
if (PacketReceivePacket(lpadapter, lppacketr, TRUE) == FALSE) {
return - 1; }
GetData(lppacketr);
} return 0; }
其中调用的函数GetData()用于解析由PacketReceivePacket()函数收到的报文,关于分析ARP_REPLY报文以便获得局域网主机列表的代码如下:
void GetData(LPPACKET lp) {
ULONG ulbytesreceived, off; ETHDR *eth; ARPHDR *arp; PIPHDR ip;
char *buf, *pChar, *base; struct bpf_hdr *hdr;
ulbytesreceived = lp->ulBytesReceived; buf = (char*)lp->Buffer;
off = 0;
while (off < ulbytesreceived) {
hdr = (struct bpf_hdr*)(buf + off); off += hdr->bh_hdrlen;
pChar = (char*)(buf + off); base = pChar;
off = Packet_WORDALIGN(off + hdr->bh_caplen);
eth = (PETHDR)pChar;
arp = (PARPHDR)(pChar + sizeof(ETHDR));
if (eth->eh_type == htons(ETH_IP)) {
ip = (PIPHDR)(pChar + sizeof(ETHDR)); for (int i = 0; i < oldHstIndex; i++) {
if ((oldHostList[i].ip == ip->sourceip || oldHostList[i].ip == ip ->destip) && oldHostList[i].sniffer == 1) {
packetList[currentPktIndex].srcIp = ip->sourceip; packetList[currentPktIndex].desIp = ip->destip; packetList[currentPktIndex].protocol = ip->proto;