static int internal_do_pingout(struct NetKeepAlive *nka) { int ret = 0; #ifdef WIN32 IP_OPTION_INFORMATION ip_option_information; int icmp_send_ret = 0; #else int len = 0; char sendbuf[1500]; #ifdef V4V6_SUPPORT struct icmp *icmp; #endif /* V4V6_SUPPORT */ struct icmp6_hdr *icmp6; #endif #ifndef WIN32 // compute packet // and send it // #ifdef V4V6_SUPPORT if (nka->family == AF_INET) { /* icmp4 packet */ icmp = (struct icmp *)sendbuf; icmp->icmp_type = ICMP_ECHO; icmp->icmp_code = 0; icmp->icmp_id = getpid(); icmp->icmp_seq = seqn++; gettimeofday((struct timeval *) icmp->icmp_data, NULL); len = 8 /* icmp header */ + 56 /* icmp data */; icmp->icmp_cksum = 0; icmp->icmp_cksum = in_cksum((u_short *) icmp, len); ret = sendto(nka->keepalive_fd, sendbuf, len, 0, (struct sockaddr *) &(nka->sa), sizeof(nka->sa)); } #endif /* V4V6_SUPPORT */ if (nka->family == AF_INET6) { icmp6 = (struct icmp6_hdr *) sendbuf; icmp6->icmp6_type = ICMP6_ECHO_REQUEST; icmp6->icmp6_code = 0; icmp6->icmp6_id = getpid(); icmp6->icmp6_seq = seqn++; gettimeofday((struct timeval *) (icmp6+1), NULL); len = 8 /* icmp header */ + 56 /* icmp data */; ret = sendto(nka->keepalive_fd, sendbuf, len, 0, (struct sockaddr *) &(nka->sa6), sizeof(nka->sa6)); } #else // WIN32 handling // memset( &ip_option_information, 0x00, sizeof(IP_OPTION_INFORMATION) ); ip_option_information.Ttl = 64; if (hEvent != NULL) { CloseHandle(hEvent); hEvent = NULL; } hEvent = CreateEvent(NULL, FALSE, FALSE, "Gw6cIcmpEvent"); // // Send a ping out then callback in // internal_do_pingin when the reply // comes in // if (nka->family == AF_INET6) { icmp_send_ret = Icmp6SendEcho2(hHandle, hEvent, NULL, NULL, &nka->sa6_local, &nka->sa6, NULL, 0, &ip_option_information, ReplyBuffer, sizeof(ReplyBuffer), 1000); if( (icmp_send_ret != 0) || ((icmp_send_ret == 0) && (GetLastError() == ERROR_IO_PENDING)) ) { // Success. ret = 1; } } #ifdef V4V6_SUPPORT else if (nka->family == AF_INET) { icmp_send_ret = IcmpSendEcho2(hHandle, hEvent, NULL, NULL, (IPAddr) nka->sa.sin_addr.S_un.S_addr, NULL, 0, &ip_option_information, ReplyBuffer, sizeof(ReplyBuffer), 1000); if( (icmp_send_ret != 0) || ((icmp_send_ret == 0) && (GetLastError() == ERROR_IO_PENDING)) ) { // Success. ret = 1; } } #endif #endif return ret; }
static void pxping_recv6(void *arg, struct pbuf *p) { struct pxping *pxping = (struct pxping *)arg; struct icmp6_echo_hdr *icmph; size_t bufsize; struct pong6 *pong; int mapped; void *reqdata; size_t reqsize; struct sockaddr_in6 src, dst; int hopl; IP_OPTION_INFORMATION opts; int status; pong = NULL; icmph = (struct icmp6_echo_hdr *)p->payload; memset(&dst, 0, sizeof(dst)); dst.sin6_family = AF_INET6; mapped = pxremap_outbound_ip6((ip6_addr_t *)&dst.sin6_addr, ip6_current_dest_addr()); if (RT_UNLIKELY(mapped == PXREMAP_FAILED)) { goto out; } hopl = IP6H_HOPLIM(ip6_current_header()); if (mapped == PXREMAP_ASIS) { if (RT_UNLIKELY(hopl == 1)) { status = pbuf_header(p, ip_current_header_tot_len()); if (RT_LIKELY(status == 0)) { icmp6_time_exceeded(p, ICMP6_TE_HL); } goto out; } --hopl; } status = pbuf_header(p, -(u16_t)sizeof(*icmph)); /* to ping payload */ if (RT_UNLIKELY(status != 0)) { goto out; } bufsize = sizeof(ICMPV6_ECHO_REPLY) + p->tot_len; pong = (struct pong6 *)malloc(sizeof(*pong) - sizeof(pong->buf) + bufsize); if (RT_UNLIKELY(pong == NULL)) { goto out; } pong->bufsize = bufsize; pong->netif = pxping->netif; ip6_addr_copy(pong->reqsrc, *ip6_current_src_addr()); memcpy(&pong->reqicmph, icmph, sizeof(*icmph)); memset(pong->buf, 0xa5, pong->bufsize); pong->reqsize = reqsize = p->tot_len; if (p->next == NULL) { /* single pbuf can be directly used as request data source */ reqdata = p->payload; } else { /* data from pbuf chain must be concatenated */ pbuf_copy_partial(p, pong->buf, p->tot_len, 0); reqdata = pong->buf; } memset(&src, 0, sizeof(src)); src.sin6_family = AF_INET6; src.sin6_addr = in6addr_any; /* let the OS select host source address */ memset(&opts, 0, sizeof(opts)); opts.Ttl = hopl; status = Icmp6SendEcho2(pxping->hdl6, NULL, pxping->callback6, pong, &src, &dst, reqdata, (WORD)reqsize, &opts, pong->buf, (DWORD)pong->bufsize, 5 * 1000 /* ms */); if (RT_UNLIKELY(status != 0)) { DPRINTF(("Icmp6SendEcho2: unexpected status %d\n", status)); goto out; } else if ((status = GetLastError()) != ERROR_IO_PENDING) { int code; DPRINTF(("Icmp6SendEcho2: error %d\n", status)); switch (status) { case ERROR_NETWORK_UNREACHABLE: case ERROR_HOST_UNREACHABLE: code = ICMP6_DUR_NO_ROUTE; break; default: code = -1; break; } if (code != -1) { /* move payload back to IP header */ status = pbuf_header(p, (u16_t)(sizeof(*icmph) + ip_current_header_tot_len())); if (RT_LIKELY(status == 0)) { icmp6_dest_unreach(p, code); } } goto out; } pong = NULL; /* callback owns it now */ out: if (pong != NULL) { free(pong); } pbuf_free(p); }
/*! * \brief * This function pings an IPv6-Address with a specified Time-To-Live-value. * * \param ai * The AddrInfo-representation of the TargetIP * * \param ttl * The Time-To-Live-value to perform the ping with * * \param out * The Buffer into which the result of the ping-command will be written * * \param outSize * The maximum number of characters that can be written into "out" * * \returns * True if the execution succeded and false otherwise. The following will be written in "out": "TARGET "+TargetIP if the target was reached, "HOP "+HopIP if an intermediate Host was reached or "NO_REPLY" if an execution error occurred. If an internal error occured, a message describing that error will be written. * * \remarks * ai will be Freed */ bool ping6(struct addrinfoW *ai, int ttl, WCHAR * out, int outSize){ // Create a handle to a hIcmpFile (required by Icmp6SendEcho2) HANDLE hIcmpFile = Icmp6CreateFile(); if (hIcmpFile == INVALID_HANDLE_VALUE) { outPutWstring(std::wstring(L"Icmp6Createfile returned error: ")+getFormatedLastError(),out,outSize); // Free all allocated resources FreeAddrInfoW(ai); return false; } // A ICMP-request using IPv6 requires a source address: Get the system's IPv6 addresses ADDRINFOW hints; memset(&hints,0,sizeof(ADDRINFOW)); hints.ai_family = AF_INET6; struct addrinfoW *lai; if(! (0==GetAddrInfoW(L"",NULL,&hints,&lai))){ outPutWstring(std::wstring(L"Invalid Socket (Localhost) : ")+getFormatedLastError(),out,outSize); // Free all allocated resources FreeAddrInfoW(ai); IcmpCloseHandle(hIcmpFile); return false; } // Out of all of the system's IPv6-addresses: get a global IPv6 IP-Address for localhost struct addrinfoW *sourceGlobal = lai; while(sourceGlobal != NULL){ sockaddr_in6 * a = (sockaddr_in6 *)sourceGlobal->ai_addr; if(IN6_IS_ADDR_GLOBAL(&a->sin6_addr)) break; sourceGlobal = sourceGlobal->ai_next; } // If there is none then there is no way to perform an ICMP-request on a IPv6-address -> abbort! if(sourceGlobal == NULL){ outPutWstring(std::wstring(L"No global IPv6 interface found on localhost: ")+getFormatedLastError(),out,outSize); // Free all allocated resources FreeAddrInfoW(ai); FreeAddrInfoW(lai); IcmpCloseHandle(hIcmpFile); return false; } // Build the payload of the ICMP-request (mustn't be empty) char SendData[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345"; // Allocate space for a single reply DWORD ReplySize = sizeof (ICMPV6_ECHO_REPLY) + sizeof (SendData) + 8 + sizeof(IO_STATUS_BLOCK); LPVOID ReplyBuffer = (VOID *) malloc(ReplySize); // Create a IP_OPTION_INFORMATION and set its TTL-field so Icmp6SendEcho2 will perform a ping with the correct TTL IP_OPTION_INFORMATION ipopts; memset(&ipopts,0,sizeof(ipopts)); ipopts.Ttl = (unsigned char)ttl; //Try to perform the actual ping DWORD dwRetVal = Icmp6SendEcho2(hIcmpFile, NULL, NULL, NULL,(sockaddr_in6 *)sourceGlobal->ai_addr, (sockaddr_in6 *)ai->ai_addr, SendData, sizeof (SendData), &ipopts, ReplyBuffer, ReplySize, 1000); if (dwRetVal == 0) { // In case it failed: Did it fail because of a timeout or because of a serious problem? bool success = false; DWORD lastError = GetLastError(); if(IP_REQ_TIMED_OUT == lastError || IP_DEST_NET_UNREACHABLE == lastError ){ // If it failed because of a Timeout return "NO_REPLY" outPutWstring(std::wstring(L"NO_REPLY"),out,outSize); success = true; } else{ // If it failed because of a serious problem return a detailed description about the failure outPutWstring(std::wstring(L"Call to Icmp6SendEcho2 failed: ")+getFormatedLastError(),out,outSize); } // Free all allocated resources FreeAddrInfoW(ai); FreeAddrInfoW(lai); free(ReplyBuffer); IcmpCloseHandle(hIcmpFile); return success; } // Parse the reply on the ICMP-request PICMPV6_ECHO_REPLY pEchoReply = (PICMPV6_ECHO_REPLY) ReplyBuffer; /* * Extract the address of the replying host */ // First: copy the reply data into a sockaddr_in6-struckture PIPV6_ADDRESS_EX pIP6Addr = &pEchoReply->Address;; sockaddr_in6 sock6; sock6.sin6_family = AF_INET6; sock6.sin6_flowinfo = pIP6Addr->sin6_flowinfo; sock6.sin6_port = pIP6Addr->sin6_port; sock6.sin6_scope_id = pIP6Addr->sin6_scope_id; memcpy(&sock6.sin6_addr, pIP6Addr->sin6_addr,sizeof(IN6_ADDR)); // Second: convert it into human readable version WCHAR ip6AddressString[256]; DWORD bufferLenght = 256; if(0 != WSAAddressToStringW((LPSOCKADDR)&sock6,sizeof(sockaddr_in6),NULL,ip6AddressString,&bufferLenght)){ outPutWstring(std::wstring(L"Call to WSAAddressToStringW failed: ")+getFormatedLastError(),out,outSize); // Free all allocated resources FreeAddrInfoW(ai); FreeAddrInfoW(lai); free(ReplyBuffer); IcmpCloseHandle(hIcmpFile); return false; } // Third: convert it into a wstring std::wstring hopName = std::wstring(ip6AddressString); /* * Switch according to status of reply */ ULONG status = pEchoReply->Status; if(status == IP_SUCCESS){ // Ping reached the target outPutWstring(std::wstring(L"TARGET ")+ hopName,out,outSize); } else if(status == IP_TTL_EXPIRED_TRANSIT || status == IP_TTL_EXPIRED_REASSEM){ // Ping got a reply from a hop on the way to target outPutWstring(std::wstring(L"HOP ")+ hopName,out,outSize); } else{ // Something didn't work outPutWstring(std::wstring(L"NO_REPLY"),out,outSize); } // Free all allocated resources free(ReplyBuffer); FreeAddrInfoW(ai); FreeAddrInfoW(lai); IcmpCloseHandle(hIcmpFile); return true; }
static void Ping(void) { PVOID ReplyBuffer = NULL; PVOID SendBuffer = NULL; DWORD ReplySize = 0; DWORD Status; SendBuffer = malloc(RequestSize); if (SendBuffer == NULL) { ConResPrintf(StdErr, IDS_NO_RESOURCES); exit(1); } ZeroMemory(SendBuffer, RequestSize); if (Family == AF_INET6) ReplySize += sizeof(ICMPV6_ECHO_REPLY); else ReplySize += sizeof(ICMP_ECHO_REPLY); ReplySize += RequestSize + SIZEOF_ICMP_ERROR + SIZEOF_IO_STATUS_BLOCK; ReplyBuffer = malloc(ReplySize); if (ReplyBuffer == NULL) { ConResPrintf(StdErr, IDS_NO_RESOURCES); free(SendBuffer); exit(1); } ZeroMemory(ReplyBuffer, ReplySize); EchosSent++; if (Family == AF_INET6) { struct sockaddr_in6 Source; ZeroMemory(&Source, sizeof(Source)); Source.sin6_family = AF_INET6; Status = Icmp6SendEcho2(hIcmpFile, NULL, NULL, NULL, &Source, (struct sockaddr_in6 *)Target->ai_addr, SendBuffer, (USHORT)RequestSize, &IpOptions, ReplyBuffer, ReplySize, Timeout); } else { Status = IcmpSendEcho2(hIcmpFile, NULL, NULL, NULL, ((PSOCKADDR_IN)Target->ai_addr)->sin_addr.s_addr, SendBuffer, (USHORT)RequestSize, &IpOptions, ReplyBuffer, ReplySize, Timeout); } free(SendBuffer); if (Status == 0) { Status = GetLastError(); switch (Status) { case IP_REQ_TIMED_OUT: ConResPrintf(StdOut, IDS_REQUEST_TIMED_OUT); break; default: ConResPrintf(StdOut, IDS_TRANSMIT_FAILED, Status); break; } } else { SOCKADDR_IN6 SockAddrIn6; SOCKADDR_IN SockAddrIn; PSOCKADDR SockAddr; socklen_t Size; EchosReceived++; ZeroMemory(&SockAddrIn, sizeof(SockAddrIn)); ZeroMemory(&SockAddrIn6, sizeof(SockAddrIn6)); if (Family == AF_INET6) { PICMPV6_ECHO_REPLY pEchoReply; PIPV6_ADDRESS_EX Ipv6Addr; pEchoReply = (PICMPV6_ECHO_REPLY)ReplyBuffer; Ipv6Addr = (PIPV6_ADDRESS_EX)&pEchoReply->Address; SockAddrIn6.sin6_family = AF_INET6; CopyMemory(SockAddrIn6.sin6_addr.u.Word, Ipv6Addr->sin6_addr, sizeof(SockAddrIn6.sin6_addr)); //SockAddrIn6.sin6_addr = Ipv6Addr->sin6_addr; SockAddr = (PSOCKADDR)&SockAddrIn6; Size = sizeof(SOCKADDR_IN6); GetNameInfoW(SockAddr, Size, Address, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); ConResPrintf(StdOut, IDS_REPLY_FROM, Address); switch (pEchoReply->Status) { case IP_SUCCESS: { EchosSuccessful++; if (pEchoReply->RoundTripTime == 0) ConResPrintf(StdOut, IDS_REPLY_TIME_0MS); else ConResPrintf(StdOut, IDS_REPLY_TIME_MS, pEchoReply->RoundTripTime); if (pEchoReply->RoundTripTime < RTTMin || RTTMin == 0) RTTMin = pEchoReply->RoundTripTime; if (pEchoReply->RoundTripTime > RTTMax || RTTMax == 0) RTTMax = pEchoReply->RoundTripTime; ConPuts(StdOut, L"\n"); RTTTotal += pEchoReply->RoundTripTime; break; } case IP_DEST_NET_UNREACHABLE: ConResPrintf(StdOut, IDS_DEST_NET_UNREACHABLE); break; case IP_DEST_HOST_UNREACHABLE: ConResPrintf(StdOut, IDS_DEST_HOST_UNREACHABLE); break; case IP_TTL_EXPIRED_TRANSIT: ConResPrintf(StdOut, IDS_TTL_EXPIRED); break; default: ConResPrintf(StdOut, IDS_REPLY_STATUS, pEchoReply->Status); break; } } else { PICMP_ECHO_REPLY pEchoReply; IPAddr *IP4Addr; pEchoReply = (PICMP_ECHO_REPLY)ReplyBuffer; IP4Addr = (IPAddr *)&pEchoReply->Address; SockAddrIn.sin_family = AF_INET; SockAddrIn.sin_addr.S_un.S_addr = *IP4Addr; SockAddr = (PSOCKADDR)&SockAddrIn; Size = sizeof(SOCKADDR_IN); GetNameInfoW(SockAddr, Size, Address, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); ConResPrintf(StdOut, IDS_REPLY_FROM, Address); switch (pEchoReply->Status) { case IP_SUCCESS: { EchosSuccessful++; ConResPrintf(StdOut, IDS_REPLY_BYTES, pEchoReply->DataSize); if (pEchoReply->RoundTripTime == 0) ConResPrintf(StdOut, IDS_REPLY_TIME_0MS); else ConResPrintf(StdOut, IDS_REPLY_TIME_MS, pEchoReply->RoundTripTime); ConResPrintf(StdOut, IDS_REPLY_TTL, pEchoReply->Options.Ttl); if (pEchoReply->RoundTripTime < RTTMin || RTTMin == 0) RTTMin = pEchoReply->RoundTripTime; if (pEchoReply->RoundTripTime > RTTMax || RTTMax == 0) RTTMax = pEchoReply->RoundTripTime; RTTTotal += pEchoReply->RoundTripTime; break; } case IP_DEST_NET_UNREACHABLE: ConResPrintf(StdOut, IDS_DEST_NET_UNREACHABLE); break; case IP_DEST_HOST_UNREACHABLE: ConResPrintf(StdOut, IDS_DEST_HOST_UNREACHABLE); break; case IP_TTL_EXPIRED_TRANSIT: ConResPrintf(StdOut, IDS_TTL_EXPIRED); break; default: ConResPrintf(StdOut, IDS_REPLY_STATUS, pEchoReply->Status); break; } } } free(ReplyBuffer); }
NTSTATUS NetworkPingThreadStart( _In_ PVOID Parameter ) { HANDLE icmpHandle = INVALID_HANDLE_VALUE; ULONG icmpCurrentPingMs = 0; ULONG icmpReplyCount = 0; ULONG icmpReplyLength = 0; PVOID icmpReplyBuffer = NULL; PPH_BYTES icmpEchoBuffer = NULL; IP_OPTION_INFORMATION pingOptions = { 255, // Time To Live 0, // Type Of Service IP_FLAG_DF, // IP header flags 0 // Size of options data }; PNETWORK_OUTPUT_CONTEXT context = (PNETWORK_OUTPUT_CONTEXT)Parameter; __try { // Create ICMP echo buffer. if (context->PingSize > 0 && context->PingSize != 32) { PPH_STRING randString; randString = PhCreateStringEx(NULL, context->PingSize * 2 + 2); // Create a random string to fill the buffer. PhGenerateRandomAlphaString(randString->Buffer, (ULONG)randString->Length / sizeof(WCHAR)); icmpEchoBuffer = PhConvertUtf16ToMultiByte(randString->Buffer); PhDereferenceObject(randString); } else { PPH_STRING version; // We're using a default length, query the PH version and use the previous buffer format. version = PhGetPhVersion(); if (version) { icmpEchoBuffer = FormatAnsiString("processhacker_%S_0x0D06F00D_x1", version->Buffer); PhDereferenceObject(version); } } if (context->IpAddress.Type == PH_IPV6_NETWORK_TYPE) { SOCKADDR_IN6 icmp6LocalAddr = { 0 }; SOCKADDR_IN6 icmp6RemoteAddr = { 0 }; PICMPV6_ECHO_REPLY2 icmp6ReplyStruct = NULL; // Create ICMPv6 handle. if ((icmpHandle = Icmp6CreateFile()) == INVALID_HANDLE_VALUE) __leave; // Set Local IPv6-ANY address. icmp6LocalAddr.sin6_addr = in6addr_any; icmp6LocalAddr.sin6_family = AF_INET6; // Set Remote IPv6 address. icmp6RemoteAddr.sin6_addr = context->IpAddress.In6Addr; icmp6RemoteAddr.sin6_port = _byteswap_ushort((USHORT)context->NetworkItem->RemoteEndpoint.Port); // Allocate ICMPv6 message. icmpReplyLength = ICMP_BUFFER_SIZE(sizeof(ICMPV6_ECHO_REPLY), icmpEchoBuffer); icmpReplyBuffer = PhAllocate(icmpReplyLength); memset(icmpReplyBuffer, 0, icmpReplyLength); InterlockedIncrement(&context->PingSentCount); // Send ICMPv6 ping... icmpReplyCount = Icmp6SendEcho2( icmpHandle, NULL, NULL, NULL, &icmp6LocalAddr, &icmp6RemoteAddr, icmpEchoBuffer->Buffer, (USHORT)icmpEchoBuffer->Length, &pingOptions, icmpReplyBuffer, icmpReplyLength, context->MaxPingTimeout ); icmp6ReplyStruct = (PICMPV6_ECHO_REPLY2)icmpReplyBuffer; if (icmpReplyCount > 0 && icmp6ReplyStruct) { BOOLEAN icmpPacketSignature = FALSE; if (icmp6ReplyStruct->Status != IP_SUCCESS) { InterlockedIncrement(&context->PingLossCount); } if (_memicmp( icmp6ReplyStruct->Address.sin6_addr, context->IpAddress.In6Addr.u.Word, sizeof(icmp6ReplyStruct->Address.sin6_addr) ) != 0) { InterlockedIncrement(&context->UnknownAddrCount); } icmpPacketSignature = _memicmp( icmpEchoBuffer->Buffer, icmp6ReplyStruct->Data, icmpEchoBuffer->Length ) == 0; if (!icmpPacketSignature) { InterlockedIncrement(&context->HashFailCount); } icmpCurrentPingMs = icmp6ReplyStruct->RoundTripTime; } else { InterlockedIncrement(&context->PingLossCount); } } else { IPAddr icmpLocalAddr = 0; IPAddr icmpRemoteAddr = 0; PICMP_ECHO_REPLY icmpReplyStruct = NULL; // Create ICMPv4 handle. if ((icmpHandle = IcmpCreateFile()) == INVALID_HANDLE_VALUE) __leave; // Set Local IPv4-ANY address. icmpLocalAddr = in4addr_any.s_addr; // Set Remote IPv4 address. icmpRemoteAddr = context->IpAddress.InAddr.s_addr; // Allocate ICMPv4 message. icmpReplyLength = ICMP_BUFFER_SIZE(sizeof(ICMP_ECHO_REPLY), icmpEchoBuffer); icmpReplyBuffer = PhAllocate(icmpReplyLength); memset(icmpReplyBuffer, 0, icmpReplyLength); InterlockedIncrement(&context->PingSentCount); // Send ICMPv4 ping... icmpReplyCount = IcmpSendEcho2Ex( icmpHandle, NULL, NULL, NULL, icmpLocalAddr, icmpRemoteAddr, icmpEchoBuffer->Buffer, (USHORT)icmpEchoBuffer->Length, &pingOptions, icmpReplyBuffer, icmpReplyLength, context->MaxPingTimeout ); icmpReplyStruct = (PICMP_ECHO_REPLY)icmpReplyBuffer; if (icmpReplyStruct && icmpReplyCount > 0) { BOOLEAN icmpPacketSignature = FALSE; if (icmpReplyStruct->Status != IP_SUCCESS) { InterlockedIncrement(&context->PingLossCount); } if (icmpReplyStruct->Address != context->IpAddress.InAddr.s_addr) { InterlockedIncrement(&context->UnknownAddrCount); } if (icmpReplyStruct->DataSize == icmpEchoBuffer->Length) { icmpPacketSignature = _memicmp( icmpEchoBuffer->Buffer, icmpReplyStruct->Data, icmpReplyStruct->DataSize ) == 0; } icmpCurrentPingMs = icmpReplyStruct->RoundTripTime; if (!icmpPacketSignature) { InterlockedIncrement(&context->HashFailCount); } } else { InterlockedIncrement(&context->PingLossCount); } } InterlockedIncrement(&context->PingRecvCount); if (context->PingMinMs == 0 || icmpCurrentPingMs < context->PingMinMs) context->PingMinMs = icmpCurrentPingMs; if (icmpCurrentPingMs > context->PingMaxMs) context->PingMaxMs = icmpCurrentPingMs; context->CurrentPingMs = icmpCurrentPingMs; PhAddItemCircularBuffer_ULONG(&context->PingHistory, icmpCurrentPingMs); } __finally { if (icmpEchoBuffer) { PhDereferenceObject(icmpEchoBuffer); } if (icmpHandle != INVALID_HANDLE_VALUE) { IcmpCloseHandle(icmpHandle); } if (icmpReplyBuffer) { PhFree(icmpReplyBuffer); } } PostMessage(context->WindowHandle, WM_PING_UPDATE, 0, 0); return STATUS_SUCCESS; }
static NTSTATUS PhNetworkPingThreadStart( _In_ PVOID Parameter ) { HANDLE icmpHandle = INVALID_HANDLE_VALUE; ULONG icmpCurrentPingMs = 0; ULONG icmpCurrentPingTtl = 0; ULONG icmpReplyCount = 0; ULONG icmpReplyLength = 0; PVOID icmpReplyBuffer = NULL; PPH_STRING phVersion = NULL; PPH_BYTES icmpEchoBuffer = NULL; IP_OPTION_INFORMATION pingOptions = { 255, // Time To Live 0, // Type Of Service IP_FLAG_DF, // IP header flags 0 // Size of options data }; PNETWORK_OUTPUT_CONTEXT context = (PNETWORK_OUTPUT_CONTEXT)Parameter; __try { // Query PH version. if ((phVersion = PhGetPhVersion()) == NULL) __leave; // Create ICMP echo buffer. if ((icmpEchoBuffer = PhFormatAnsiString("processhacker_%S_0x0D06F00D_x1", phVersion->Buffer)) == NULL) __leave; if (context->IpAddress.Type == PH_IPV6_NETWORK_TYPE) { SOCKADDR_IN6 icmp6LocalAddr = { 0 }; SOCKADDR_IN6 icmp6RemoteAddr = { 0 }; PICMPV6_ECHO_REPLY icmp6ReplyStruct = NULL; // Create ICMPv6 handle. if ((icmpHandle = Icmp6CreateFile()) == INVALID_HANDLE_VALUE) __leave; // Set Local IPv6-ANY address. icmp6LocalAddr.sin6_addr = in6addr_any; icmp6LocalAddr.sin6_family = AF_INET6; // Set Remote IPv6 address. icmp6RemoteAddr.sin6_addr = context->IpAddress.In6Addr; icmp6RemoteAddr.sin6_port = _byteswap_ushort((USHORT)context->NetworkItem->RemoteEndpoint.Port); // Allocate ICMPv6 message. icmpReplyLength = ICMP_BUFFER_SIZE(sizeof(ICMPV6_ECHO_REPLY), icmpEchoBuffer); icmpReplyBuffer = PhAllocate(icmpReplyLength); memset(icmpReplyBuffer, 0, icmpReplyLength); InterlockedIncrement(&context->PingSentCount); // Send ICMPv6 ping... icmpReplyCount = Icmp6SendEcho2( icmpHandle, NULL, NULL, NULL, &icmp6LocalAddr, &icmp6RemoteAddr, icmpEchoBuffer->Buffer, (USHORT)icmpEchoBuffer->Length, &pingOptions, icmpReplyBuffer, icmpReplyLength, context->MaxPingTimeout ); icmp6ReplyStruct = (PICMPV6_ECHO_REPLY)icmpReplyBuffer; if (icmpReplyCount > 0 && icmp6ReplyStruct) { BOOLEAN icmpPacketSignature = FALSE; if (icmp6ReplyStruct->Status != IP_SUCCESS) { InterlockedIncrement(&context->PingLossCount); } if (_memicmp( icmp6ReplyStruct->Address.sin6_addr, context->IpAddress.In6Addr.u.Word, sizeof(icmp6ReplyStruct->Address.sin6_addr) ) != 0) { InterlockedIncrement(&context->UnknownAddrCount); } //if (icmp6ReplyStruct->DataSize == icmpEchoBuffer->MaximumLength) //{ // icmpPacketSignature = (_memicmp( // icmpEchoBuffer->Buffer, // icmp6ReplyStruct->Data, // icmp6ReplyStruct->DataSize // ) == 0); //} //if (icmpPacketSignature != TRUE) //{ // InterlockedIncrement(&context->HashFailCount); //} icmpCurrentPingMs = icmp6ReplyStruct->RoundTripTime; //icmpCurrentPingTtl = icmp6ReplyStruct->Options.Ttl; } else { InterlockedIncrement(&context->PingLossCount); } } else { IPAddr icmpLocalAddr = 0; IPAddr icmpRemoteAddr = 0; PICMP_ECHO_REPLY icmpReplyStruct = NULL; // Create ICMPv4 handle. if ((icmpHandle = IcmpCreateFile()) == INVALID_HANDLE_VALUE) __leave; // Set Local IPv4-ANY address. icmpLocalAddr = in4addr_any.s_addr; // Set Remote IPv4 address. icmpRemoteAddr = context->IpAddress.InAddr.s_addr; // Allocate ICMPv4 message. icmpReplyLength = ICMP_BUFFER_SIZE(sizeof(ICMP_ECHO_REPLY), icmpEchoBuffer); icmpReplyBuffer = PhAllocate(icmpReplyLength); memset(icmpReplyBuffer, 0, icmpReplyLength); InterlockedIncrement(&context->PingSentCount); // Send ICMPv4 ping... //if (WindowsVersion > WINDOWS_VISTA) //{ // // Vista SP1 and up we can specify the source address: // icmpReplyCount = IcmpSendEcho2Ex( // icmpHandle, // NULL, // NULL, // NULL, // icmpLocalAddr, // icmpRemoteAddr, // icmpEchoBuffer->Buffer, // icmpEchoBuffer->MaximumLength, // &pingOptions, // icmpReplyBuffer, // icmpReplyLength, // context->MaxPingTimeout // ); //} icmpReplyCount = IcmpSendEcho2( icmpHandle, NULL, NULL, NULL, icmpRemoteAddr, icmpEchoBuffer->Buffer, (USHORT)icmpEchoBuffer->Length, &pingOptions, icmpReplyBuffer, icmpReplyLength, context->MaxPingTimeout ); icmpReplyStruct = (PICMP_ECHO_REPLY)icmpReplyBuffer; if (icmpReplyStruct && icmpReplyCount > 0) { BOOLEAN icmpPacketSignature = FALSE; if (icmpReplyStruct->Status != IP_SUCCESS) { InterlockedIncrement(&context->PingLossCount); } if (icmpReplyStruct->Address != context->IpAddress.InAddr.s_addr) { InterlockedIncrement(&context->UnknownAddrCount); } if (icmpReplyStruct->DataSize == icmpEchoBuffer->Length) { icmpPacketSignature = (_memicmp( icmpEchoBuffer->Buffer, icmpReplyStruct->Data, icmpReplyStruct->DataSize ) == 0); } icmpCurrentPingMs = icmpReplyStruct->RoundTripTime; icmpCurrentPingTtl = icmpReplyStruct->Options.Ttl; if (!icmpPacketSignature) { InterlockedIncrement(&context->HashFailCount); } } else { InterlockedIncrement(&context->PingLossCount); } } InterlockedIncrement(&context->PingRecvCount); if (context->PingMinMs == 0 || icmpCurrentPingMs < context->PingMinMs) context->PingMinMs = icmpCurrentPingMs; if (icmpCurrentPingMs > context->PingMaxMs) context->PingMaxMs = icmpCurrentPingMs; context->CurrentPingMs = icmpCurrentPingMs; PhAddItemCircularBuffer_ULONG(&context->PingHistory, icmpCurrentPingMs); } __finally { if (phVersion) { PhDereferenceObject(phVersion); } if (icmpEchoBuffer) { PhDereferenceObject(icmpEchoBuffer); } if (icmpHandle != INVALID_HANDLE_VALUE) { IcmpCloseHandle(icmpHandle); } if (icmpReplyBuffer) { PhFree(icmpReplyBuffer); } } PostMessage(context->WindowHandle, WM_PING_UPDATE, 0, 0); return STATUS_SUCCESS; }