// ICMP.cpp: implementation of the CICMP class. // //////////////////////////////////////////////////////////////////////
#include "stdafx.h" #include "RouteTrace.h" #include "ICMP.h" #include "ws2tcpip.h" //实现 IP_TTL 设置的关键
#ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif
////////////////////////////////////////////////////////////////////// // Construction/Destruction //////////////////////////////////////////////////////////////////////
CICMP::CICMP() { winsock = 0; m_pIp = NULL; m_pIcmp = NULL;
m_pIp = (IP_HEAD *)new BYTE[MAX_PACKET]; m_pIcmp = (ICMP_HEAD *)new BYTE[MAX_PACKET];
}
CICMP::~CICMP() { delete [] m_pIp; delete [] m_pIcmp; }
BOOL CICMP::Initialize() { WSADATA wsadata; if( WSAStartup(MAKEWORD(2, 1),&wsadata) ) { AfxMessageBox("WSAStartup初始化失败!"); return FALSE; }
winsock= WSASocket (AF_INET, //建立socket SOCK_RAW, IPPROTO_ICMP, NULL, 0,0); if(!winsock) { AfxMessageBox( "Socket创建失败!"); return FALSE; }
int timeout =5000; setsockopt(winsock,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout, // 设置接收超时 sizeof(timeout)); timeout = 5000; setsockopt(winsock,SOL_SOCKET,SO_SNDTIMEO,(char *)&timeout, //设置发送超时 sizeof(timeout));
return TRUE; }
void CICMP::Uninitialize() //释放Socket { if(winsock) closesocket(winsock); WSACleanup(); }
USHORT CICMP::CheckSum(USHORT *buffer, int size) //计算校验和 { unsigned long cksum = 0; while(size > 1) { cksum+=*buffer++; size -=sizeof(USHORT); }
if(size ) { cksum += *(UCHAR*)buffer; }
cksum = (cksum >> 16) + (cksum & 0xffff); cksum += (cksum >>16);
return (USHORT)(~cksum); } //--------------------发送ICMP回应请求报文-------------------
BOOL CICMP::SendICMPPack(char *pAddr) { sockaddr_in sockAddr; memset((void *)&sockAddr,0,sizeof(sockAddr)); sockAddr.sin_family = AF_INET; sockAddr.sin_port = 0; sockAddr.sin_addr.S_un.S_addr=inet_addr(pAddr);
return SendICMPPack(&sockAddr); } BOOL CICMP::SendICMPPack(sockaddr_in *pAddr) { //填充ICMP数据各项 int state; char *p_data; m_pIcmp->type = ICMP_ECHO; m_pIcmp->code = 0; m_pIcmp->ID = (USHORT)GetCurrentProcessId(); m_pIcmp->number = 0; m_pIcmp->time = GetTickCount(); m_pIcmp->cksum = 0;
//填充数据 p_data = ((char *)m_pIcmp + sizeof(ICMP_HEAD)); memset((char *)p_data,''0'',DEF_PACKET);
//校验和 m_pIcmp->cksum = CheckSum((USHORT *)m_pIcmp, DEF_PACKET+sizeof(ICMP_HEAD));
//发送数据 state = sendto(winsock,(char *)m_pIcmp, DEF_PACKET+sizeof(ICMP_HEAD), NULL,(struct sockaddr *)pAddr,sizeof(sockaddr));
if(state == SOCKET_ERROR) { if(GetLastError()==WSAETIMEDOUT) m_strInfo = "连接超时!(发送)"; else m_strInfo.Format("出现未知发送错误!"); return FALSE; }
if(state <DEF_PACKET) { m_strInfo = "发送数据错误!"; return FALSE; }
memcpy((void *)&m_sockAddr,(void *)pAddr, sizeof(sockaddr_in));
return TRUE; }
//----------------------接收数据---------------------------- BOOL CICMP::RecvICMPPack() { int state; int len = sizeof(sockaddr_in); char * addr; struct hostent *lpHostent = NULL;
addr = inet_ntoa(m_sockAddr.sin_addr); state = recvfrom(winsock,(char *)m_pIp,MAX_PACKET,0, (struct sockaddr*)&m_sockAddr,&len);
if (state == SOCKET_ERROR) { if (WSAGetLastError() == WSAETIMEDOUT) { m_strInfo="接收超时,路由跟踪失败!"; routestate=0; RouteState="路由跟踪失败!"; } else m_strInfo = "未知接收错误!"; return FALSE; }
//分析数据 int ipheadlen; ipheadlen = m_pIp->HeadLen * 4 ;
if (state < (ipheadlen+MIN_PACKET)) { m_strInfo = "目的地址的响应数据不正确"; return FALSE; }
ICMP_HEAD * p_icmprev; p_icmprev = (ICMP_HEAD*)((char *)m_pIp + ipheadlen);
switch (p_icmprev->type) { case ICMP_ECHOREPLY: //收到正常回显 { m_strInfo.Format("接收到%s %d字节响应数据,响应时间:%dms.", inet_ntoa(m_sockAddr.sin_addr),len,GetTickCount()-p_icmprev->time); routeaddr=addr; routestate=0; RouteState="到达目的主机!"; return TRUE; break; } case ICMP_TTLOUT: // TTL超时 { routeaddr=inet_ntoa(m_sockAddr.sin_addr); routestate=1; RouteState="测试到路由器!"; return TRUE; break; }
case ICMP_DESUNREACH: //目的不可达 { m_strInfo = "目的不可达!"; routestate=0; RouteState="目的不可达!"; return TRUE; break; }
default :{ routestate=0; m_strInfo="未知错误!"; RouteState="不明状态!"; } } return TRUE;
} //----------------设置TTL-------------------- int CICMP::SetTTL(int TTL) { int nRet=setsockopt(winsock, IPPROTO_IP, IP_TTL,(LPSTR)&TTL,sizeof(int));
if(nRet==SOCKET_ERROR) { CString ttlerr; ttlerr.Format("设置 TTL 错误!"); AfxMessageBox(ttlerr); return 0; } return 1; }
RouteTraceDlg.cpp文件代码:// RouteTraceDlg.cpp : implementation file // #include "stdafx.h" #include "RouteTrace.h" #include "RouteTraceDlg.h" #include "afxmt.h"
#ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif
///////////////////////////////////////////////////////////////////////////// // CAboutDlg dialog used for App About struct SubThreadInfo { CDialog* pDialog; CListCtrl* list; CStatic* state; CString IPStr; int Maxhot;
} Info;
CEvent eventStopRoute; //-----------------路由跟踪线程--------------- UINT ThreadRoute(LPVOID pParam) { SubThreadInfo* pInfo = (SubThreadInfo*)pParam; CRouteTraceDlg* pThreadDlg = (CRouteTraceDlg*)pInfo->pDialog;
CICMP m_icmp; CString IPStr=pInfo->IPStr; CString sTTL; int nTtl; m_icmp.Initialize(); for(nTtl=1;nTtl<=pInfo->Maxhot;nTtl++) { if(m_icmp.SetTTL(nTtl)==0) return 0; sTTL.Format("%d",nTtl); if(m_icmp.SendICMPPack((char *)(LPCSTR)IPStr)) m_icmp.RecvICMPPack();
{ int i=pInfo->list->InsertItem(0,sTTL); pInfo->list->SetItemText(i,1,m_icmp.routeaddr); pInfo->list->SetItemText(i,2,m_icmp.RouteState); pInfo->state->SetWindowText(m_icmp.m_strInfo); Sleep(100); } if(m_icmp.routestate==0) //收到非TTL超时报文则跳出循环 break; if(WaitForSingleObject(eventStopRoute.m_hObject, 0) == WAIT_OBJECT_0) break; //收到停止信号则跳出循环 } pThreadDlg->Routeflag=TRUE;
return 0; }
…… //系统代码
BOOL CRouteTraceDlg::OnInitDialog() { CDialog::OnInitDialog();
…… //系统代码
// TODO: Add extra initialization here m_list.InsertColumn(0,"标号",LVCFMT_CENTER,60,0); m_list.InsertColumn(1,"路由器地址",HDF_CENTER,200,0); m_list.InsertColumn(2,"状态",HDF_CENTER,100,0);
ListView_SetExtendedListViewStyleEx(m_list.m_hWnd, LVS_EX_FULLROWSELECT, 0xFFFFFFFF);
return TRUE; // return TRUE unless you set the focus to a control }
…… //系统代码
void CRouteTraceDlg::OnTrace() { CString str; UpdateData(TRUE); CWnd * pWnd; pWnd = GetDlgItem(IDC_COMBO); pWnd->GetWindowText(str);
if(str.IsEmpty()) { MessageBox("请输入地址!"); pWnd->SetFocus(); return; } if (m_comb.FindStringExact(-1, str) == CB_ERR) m_comb.AddString(str);
m_list.DeleteAllItems(); if(Routeflag) { Routeflag=FALSE; Info.IPStr=str; Info.pDialog=this; Info.Maxhot=m_maxhot; Info.list=(&m_list); Info.state=(&m_statectl); AfxBeginThread(ThreadRoute, &Info); //在线程中实现路由跟踪 } }
void CRouteTraceDlg::OnStop() { if(!Routeflag) { eventStopRoute.SetEvent(); // 发出停止信号 } }
void CRouteTraceDlg::OnDestroy() { CDialog::OnDestroy();
// TODO: Add your message handler code here m_icmp.Uninitialize(); } |