📄 tracert.c
字号:
{
_tprintf(_T(" * "));
}
else if ((iSelRet != SOCKET_ERROR) && (iSelRet != 0))
{
iSockRet = recvfrom(pInfo->icmpSock, // socket
(char *)pInfo->RecvPacket, // buffer
MAX_PING_PACKET_SIZE, // size of buffer
0, // flags
(SOCKADDR *)&pInfo->source, // source address
&iFromLen); // address length
if (iSockRet != SOCKET_ERROR)
{
/* get time packet was recieved */
pInfo->lTimeEnd = GetTime(pInfo);
DebugPrint(_T("reveived %d bytes\n"), iSockRet);
bRet = TRUE;
}
else
{
DebugPrint(_T("recvfrom failed: %d\n"), WSAGetLastError());
}
}
return bRet;
}
static INT
DecodeResponse(PAPPINFO pInfo)
{
unsigned short header_len = pInfo->RecvPacket->h_len * 4;
/* cast the recieved packet into an ECHO reply and a TTL Exceed and check the ID*/
ECHO_REPLY_HEADER *IcmpHdr = (ECHO_REPLY_HEADER *)((char*)pInfo->RecvPacket + header_len);
TTL_EXCEED_HEADER *TTLExceedHdr = (TTL_EXCEED_HEADER *)((char *)pInfo->RecvPacket + header_len);
/* Make sure the reply is ok */
if (PACKET_SIZE < header_len + ICMP_MIN_SIZE)
{
DebugPrint(_T("too few bytes from %s\n"), inet_ntoa(pInfo->dest.sin_addr));
return -2;
}
switch (IcmpHdr->icmpheader.type)
{
case TTL_EXCEEDED :
if (TTLExceedHdr->OrigIcmpHeader.id != (USHORT)GetCurrentProcessId())
{
/* FIXME: our network stack shouldn't allow this... */
/* we've picked up a packet not related to this process probably from another local program. We ignore it */
DebugPrint(_T("Rouge packet: header id, process id %d"), TTLExceedHdr->OrigIcmpHeader.id, GetCurrentProcessId());
return -1;
}
_tprintf(_T("%3Ld ms"), (pInfo->lTimeEnd - pInfo->lTimeStart) / pInfo->TicksPerMs.QuadPart);
return 0;
case ECHO_REPLY :
if (IcmpHdr->icmpheader.id != (USHORT)GetCurrentProcessId())
{
/* FIXME: our network stack shouldn't allow this... */
/* we've picked up a packet not related to this process probably from another local program. We ignore it */
DebugPrint(_T("Rouge packet: header id %d, process id %d"), IcmpHdr->icmpheader.id, GetCurrentProcessId());
return -1;
}
_tprintf(_T("%3Ld ms"), (pInfo->lTimeEnd - pInfo->lTimeStart) / pInfo->TicksPerMs.QuadPart);
return 1;
case DEST_UNREACHABLE :
_tprintf(_T(" * "));
return 2;
}
return 0;
}
static BOOL
AllocateBuffers(PAPPINFO pInfo)
{
pInfo->SendPacket = (PECHO_REPLY_HEADER)HeapAlloc(GetProcessHeap(),
0,
sizeof(ECHO_REPLY_HEADER) + PACKET_SIZE);
if (!pInfo->SendPacket)
return FALSE;
pInfo->RecvPacket = (PIPv4_HEADER)HeapAlloc(GetProcessHeap(),
0,
sizeof(IPv4_HEADER) + PACKET_SIZE);
if (!pInfo->RecvPacket)
{
HeapFree(GetProcessHeap(),
0,
pInfo->SendPacket);
return FALSE;
}
return TRUE;
}
static INT
Driver(PAPPINFO pInfo)
{
INT iHopCount = 1; // hop counter. default max is 30
BOOL bFoundTarget = FALSE; // Have we reached our destination yet
INT iRecieveReturn; // RecieveReturn return value
PECHO_REPLY_HEADER icmphdr;
INT iTTL = 1;
INT ret = -1;
//temps for getting host name
CHAR cHost[256];
CHAR cServ[256];
CHAR *ip;
SetupTimingMethod(pInfo);
if (AllocateBuffers(pInfo) &&
ResolveHostname(pInfo) &&
CreateSocket(pInfo))
{
/* print tracing info to screen */
_tprintf(_T("\nTracing route to %s [%s]\n"), cHostname, cDestIP);
_tprintf(_T("over a maximum of %d hop"), pInfo->iMaxHops);
pInfo->iMaxHops > 1 ? _tprintf(_T("s:\n\n")) : _tprintf(_T(":\n\n"));
/* run until we hit either max hops, or find the target */
while ((iHopCount <= pInfo->iMaxHops) &&
(bFoundTarget != TRUE))
{
USHORT iSeqNum = 0;
INT i;
_tprintf(_T("%3d "), iHopCount);
/* run 3 pings for each hop */
for (i = 0; i < 3; i++)
{
if (SetTTL(pInfo->icmpSock, iTTL) != TRUE)
{
DebugPrint(_T("error in Setup()\n"));
return ret;
}
PreparePacket(pInfo, iSeqNum);
if (SendPacket(pInfo) != SOCKET_ERROR)
{
BOOL bAwaitPacket = FALSE; // indicates whether we have recieved a good packet
do
{
/* Receive replies until we get a successful read, or a fatal error */
if ((iRecieveReturn = ReceivePacket(pInfo)) < 0)
{
/* FIXME: consider moving this into RecievePacket */
/* check the seq num in the packet, if it's bad wait for another */
WORD hdrLen = pInfo->RecvPacket->h_len * 4;
icmphdr = (ECHO_REPLY_HEADER *)((char*)&pInfo->RecvPacket + hdrLen);
if (icmphdr->icmpheader.seq != iSeqNum)
{
_tprintf(_T("bad sequence number!\n"));
continue;
}
}
if (iRecieveReturn)
{
DecodeResponse(pInfo);
}
else
/* packet timed out. Don't wait for it again */
bAwaitPacket = FALSE;
} while (bAwaitPacket);
}
iSeqNum++;
_tprintf(_T(" "));
}
if(pInfo->bResolveAddresses)
{
INT iNameInfoRet; // getnameinfo return value
/* gethostbyaddr() and getnameinfo() are
* unimplemented in ROS at present.
* Alex has advised he will be implementing getnameinfo.
* I've used that for the time being for testing in Windows*/
//ip = inet_addr(inet_ntoa(source.sin_addr));
//host = gethostbyaddr((char *)&ip, 4, 0);
ip = inet_ntoa(pInfo->source.sin_addr);
iNameInfoRet = getnameinfo((SOCKADDR *)&pInfo->source,
sizeof(SOCKADDR),
cHost,
256,
cServ,
256,
NI_NUMERICSERV);
if (iNameInfoRet == 0)
{
/* if IP address resolved to a hostname,
* print the IP address after it */
if (lstrcmpA(cHost, ip) != 0)
_tprintf(_T("%s [%s]"), cHost, ip);
else
_tprintf(_T("%s"), cHost);
}
else
{
DebugPrint(_T("error: %d"), WSAGetLastError());
DebugPrint(_T(" getnameinfo failed: %d"), iNameInfoRet);
}
}
else
_tprintf(_T("%s"), inet_ntoa(pInfo->source.sin_addr));
_tprintf(_T("\n"));
/* check if we've arrived at the target */
if (strcmp(cDestIP, inet_ntoa(pInfo->source.sin_addr)) == 0)
bFoundTarget = TRUE;
else
{
iTTL++;
iHopCount++;
Sleep(500);
}
}
_tprintf(_T("\nTrace complete.\n"));
ret = 0;
}
return ret;
}
static VOID
Cleanup(PAPPINFO pInfo)
{
if (pInfo->icmpSock)
closesocket(pInfo->icmpSock);
WSACleanup();
if (pInfo->SendPacket)
HeapFree(GetProcessHeap(),
0,
pInfo->SendPacket);
if (pInfo->SendPacket)
HeapFree(GetProcessHeap(),
0,
pInfo->RecvPacket);
}
#if defined(_UNICODE) && defined(__GNUC__)
static
#endif
int _tmain(int argc, LPCTSTR argv[])
{
PAPPINFO pInfo;
WSADATA wsaData;
int ret = -1;
pInfo = (PAPPINFO)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(APPINFO));
if (pInfo)
{
pInfo->bResolveAddresses = TRUE;
pInfo->iMaxHops = 30;
pInfo->iTimeOut = 1000;
if (ParseCmdline(argc, argv, pInfo))
{
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
DebugPrint(_T("WSAStartup failed.\n"));
}
else
{
ret = Driver(pInfo);
Cleanup(pInfo);
}
}
HeapFree(GetProcessHeap(),
0,
pInfo);
}
return ret;
}
#if defined(_UNICODE) && defined(__GNUC__)
/* HACK - MINGW HAS NO OFFICIAL SUPPORT FOR wmain()!!! */
int main( int argc, char **argv )
{
WCHAR **argvW;
int i, j, Ret = 1;
if ((argvW = malloc(argc * sizeof(WCHAR*))))
{
/* convert the arguments */
for (i = 0, j = 0; i < argc; i++)
{
if (!(argvW[i] = malloc((strlen(argv[i]) + 1) * sizeof(WCHAR))))
{
j++;
}
swprintf(argvW[i], L"%hs", argv[i]);
}
if (j == 0)
{
/* no error converting the parameters, call wmain() */
Ret = wmain(argc, (LPCTSTR *)argvW);
}
/* free the arguments */
for (i = 0; i < argc; i++)
{
if (argvW[i])
free(argvW[i]);
}
free(argvW);
}
return Ret;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -