CPing v1.53
Welcome to CPing, a freeware C++ class to encapsulate the "Ping" on
Windows
Features
- Simple and clean C++ interface.
- The interface provided is synchronous which provides an easier programming
model than using asynchronous sockets.
- A configurable timeout for the connection can be set through the class API.
- The classes are fully Unicode compliant and include Unicode built options
in the workspace file.
- As of v1.46, the classes are only supported on VC 2017 or later.
Usage
- To use the class in your code simply include ping.cpp in your project and
#include ping.h in which ever of your modules needs to make calls to the class.
History
v1.53 (18 March 2022)
- Updated copyright details.
- Updated the code to use C++ uniform initialization for all variable
declarations.
v1.52 (10 December 2021)
- Made a number of methods nodiscard.
- Replaced ATL::CHeapPtr<BYTE> with std::vector<BYTE>.
v1.51 (30 March 2021)
- Updated copyright details.
- Updated the PingUsingICMPv4 and PingUsingICMPv6 methods to preserve the
last error value across calls to IcmpCloseHandle. Thanks to Geoff Shapiro
for reporting this issue.
v1.50 (28 March 2020)
- Updated copyright details.
- Fixed more Clang-Tidy static code analysis warnings in the code.
v1.49 (29 December 2019)
- Fixed various Clang-Tidy static code analysis warnings in the code.
v1.48 (10 November 2019)
- Updated initialization of various structs to use C++ 11 list
initialization
- Replaced BOOL with bool in a number of places throughout the codebase
v1.47 (3 May 2019)
- Updated copyright details.
- Updated the code to clean compile on VC 2019
v1.46 (3 November 2018)
- Updated copyright details.
- Fixed a number of C++ core guidelines compiler warnings. These changes
mean that the code will now only compile on VC 2017 or later.
- Removed all code which used GetProcAddress in the sample app.
v1.45 (26 December 2017)
- Updated copyright details.
- Replaced CString::operator LPC*STR() calls throughout the codebase with
CString::GetString calls
- Replaced NULL throughout the codebase with nullptr. This means that the
minimum requirement for the code is now VC 2010.
- Removed all the code which uses GetProcAddress to access the functions
in Iphlpapi.dll. Instead now the code implicitly links to Iphlpapi.dll.
v1.44 (8 May 2016)
- Minor update to the header file inclusions in ping.cpp, ping.h and
stdafx.h
v1.43 (6 May 2016)
- Split CPingReply class into two separate CPingReplyv4 and CPingReplyv6 classes.
v1.42 (2 May 2016)
- Updated copyright details.
- Updated the sample project settings to more modern default values.
- Updated the code to compile cleanly on VC 2010 - 2015.
- Replaced all calls to TRACE with ATLTRACE
- Code no longer uses LoadLibrary without an absolute path when loading
Iphlpapi / ICMP dlls. This avoids DLL planting security issues.
- Removed code from CPing::DecodeResponse which checks i_type & i_id
header values.
- Made class MFC independent. Now the code only depends on ATL.
- Removed code from CPing::PingUsingICMP which parses the response.
- Added support for IPv6 in addition to IPv4. This means that the minimum
supported version of VC which supports CPing is now VC 2008. The sample now
ships with a VC 2008 solution.
- Code now supports IcmpSendEcho2Ex which supports IPv4 source address
binding
- Removed the PingUsingWinsock method from the class as all the ping
functionality can now be achieved via the Icmp* Windows API calls. This
means that the CPING_NO_ICMP and CPING_NO_WINSOCK2 preprocessor values are
defunct and have been removed.
- Added SAL annotations to all the code.
- Added support for the IP_FLAG_REVERSE IP_OPTION_INFORMATION flag.
- Addition of GetICMP_ECHO_REPLY and GetICMPV6_ECHO_REPLY methods to
the CPingReply class which allow access to the raw ICMP echo reply
structure.
v1.41 (7 June 2008)
- Updated copyright details
- Updated the sample app to clean compile on VC 2008
- Code now compiles cleanly using Code Analysis (/analyze)
- The code has now been updated to support VC 2005 or later only
- Replaced all calls to ZeroMemory with memset
- Code now uses ATL::CHeapPtr for managed raw buffers
- The "Bind", "FillIcmpData", "DecodeResponse" and "GenerateIPChecksum"
methods have been made virtual. This for example allows client code to
decide what data gets put into ICMP request packets. Thanks to Dinci Glas
for prompting this update.
v1.40 (10 July 2006)
- Updated copyright details
- The code now requires the Platform SDK if compiled using VC 6.
- Integrated the functionality of _CPING_ICMP class into CPing
- Optimized CPingReply constructor code
- Code now uses newer C++ style casts instead of C style casts.
- Addition of CPING_EXT_CLASS macro to allow the code to be easily added to
an extension dll.
- Code now uses newer C++ style casts instead of C style casts.
- Updated the code to clean compile on VC 2005.
- Updated documentation to use the same style as the web site.
v1.39 (31 July 2005)
- Now the PingUsingICMP method using the versions provided in the IP Helper
dll namely "Iphlpapi.dll" before falling back to "ICMP.dll".
- Tidied up the various ICMP defines by making them part of the _CPING_ICMP
class
v1.38 (31 July 2005)
- When sending a ping, the allowable size of the data in the packet can now
be anywhere from 0 to 65500. Previosuly sending a ping using Winsock was limited
to a data size of 1024 and when using ICMP.dll, the size was limited to 255.
Thanks to Leon Luu for reporting this issue.
v1.37 (11 June 2005)
- Reviewed all TRACE statements for correctness. Thanks to "Grenal" for reporting
this issue.
- Checked all premature return points in the codebase to ensure the last error
value is preserved.
- Fixed an unreferrenced variable in DecodeResponse function when code is
compiled with Visual Studio .NET 2003
v1.36 (12 April 2004)
- Fixed a bug in the declaration of h_len and version in the IP_HEADER structure.
Also made the source and destination IP addresses longs instead of ints to avoid
any porting problems. Thanks to Yuh-Rong Leu for reporting this problem.
- Fixed a bug in PingUsingWinsock when a timeout occurs and it returns TRUE.
Thanks to Yuh-Rong Leu for reporting this problem.
- Updated the documentation to refer to using the value from GetCurrentThreadId()
for the nSequenceNumber parameter when calling the PingUsingWinsock function.
Again thanks to Yuh-Rong Leu for reporting this issue.
- Fixed an issue in DecodeResponse where if bTryAgain was set to TRUE, the
return value was incorrectly also being set to TRUE. Thanks to Yuh-Rong Leu
for reporting this issue.
v1.35 (23 November 2003)
- Fixed a level 4 warning in VC 6 in the function CPing::PingUsingWinsock.
27 June 2003
- Updated the documentation including description of PingUsingWinsock function
plus a general review
v1.34 (13 March 2003)
- Fixed a bug in CPing::IsSocketReadible in the setup of the timeval structure.
Thanks to "InBloom Support" for reporting this.
v1.33 (10 March 2003)
- Fixed a bug where using PingUsingWinsock and setting the data size greater
than 1004 appears to cause Winsock error 10040 - The datagram is too large to
fit into the buffer and is truncated. Thanks to Paul Golightly for reported
this and provided the fix.
v1.32 (22 November 2002)
- Fixed an issue in the calculation of the packet size when sending using
raw sockets.
- Default sample now uses a default TTL of 30
- Changes the nPacketSize parameter to the Ping method to be nDataSize which
is what it really is.
- Reviewed all the TRACE messages for correctness
- Made all the helper functions used by the code member functions of the class
- General tidy up of the various defines
- Winsock 2 version of ping now allows you to specify the sequence number
of the packet. This allows the ping to exclude packets from the same process
id which are being generated by for example another thread.
- Fixed a bug in the call to recvfrom. The receive buffer size was not being
specified correctly.
- ICMP response packets from other processes are now ignored when waiting
for an ICMP response
- ICMP response packets from the same process but which have an incorrect
sequence number are now ignored when waiting for an ICMP response.
- Fix a resource leak of a socket when unexpected failures occur in the CPing::PingUsingWinsock
function
v1.31 (5 May 2002)
- Now includes a EchoReplyStatus in CPingReply structure if CPING_NO_ICMP
is not defined.
v1.3 (25 February 2002)
- Winsock 2 code path now allows you to bind the socket to a specific NIC.
This can prove useful when you want to run a targeted ping request on a mulithoned
machine.
- Tidied up the code in the sample application
- Provide a complete set of command line options for the sample app. It now
provides almost a 1 - 1 implementation of the built in Ping options.
- Completed reworked and recoded all the CPing code.
- Client code is now responsible for initializing Winsock instead of having
it embedded in the CPing code.
v1.24 (12 January 2002)
- Updated copyright information.
- Now initializes Winsock 2.0 instead of Winsock 2.1. Thanks to Lev Elbert
for spotting this problem.
v1.23 (15 July 2001)
- Updated copyright information
- Code now automatically pulls in the Winsock 2 libraries as and when needed
v1.22 (1 March 2000)
- Fixed a problem where I was incorrectly overwriting memory in the function
FillIcmpData.
- tidied up the console info issued by CPing.
v1.21 (9 November 1998)
- Now ships with a VC 5 workspace file instead of VC 6. This is mainly because
VC 6 is still not as stable as VC 5 plus a lot of people have not migrated to
it yet.
- Workspace file now includes configurations to allow both the Winsock 2 and
ICMP based code to be exercised.
- Fixed a level 4 warning which was occurring.
- Removed a number of compiler errors which was occurring when code was compiled
to use the ICMP or Winsock 2.
- Fixed a bug whereby a ping to a non-existent host using the Winsock 2 method
blocked indefinitely.
- Fixed a socket handle leak which was occurring if the Winsock 2 method of
pinging was used.
- Fixed error in API documentation when compared with the actual header file.
- Fixed error in API documentation regarding default timeouts value.
v1.2 (30 July 1998)
- Can now use both Winsock 2 calls and ICMP style calls at the same time with
the use of 2 pre-processor directives.
- sample program now use generic entry point _tmain.
- Got rid of a 2 level 4 compiler warnings.
- Fixed a problem with the cleanup of ICMP dll usage.
- Tidied up and optimized the usage of static variables.
v1.1 (23 June 1998)
- The class now supports using Winsock 2 calls instead of using the ICMP dll.
To use Winsock 2 calls in CPing instead of the ICMP dll, just define the pre-processor
constant "CPING_USE_WINSOCK2" and don't forget to link to "ws2_32.lib".
v1.0 (11 June 1998)
API Reference
The API consists of the various public members of the class CPing
CPing::PingUsingICMP
bool CPing::PingUsingICMPv4(LPCTSTR pszHostName,
CPingReplyv4& pr, UCHAR nTTL = 10,
DWORD dwTimeout = 5000, WORD wDataSize =
32, UCHAR nTOS = 0, bool bDontFragment
= false, bool bFlagReverse
= false, LPCTSTR pszLocalBoundAddress = nullptr)
const
bool CPing::PingUsingICMPv6(LPCTSTR pszHostName,
CPingReplyv6& pr, UCHAR nTTL = 10,
DWORD dwTimeout = 5000, WORD wDataSize =
32, UCHAR nTOS = 0, bool bDontFragment
= false, bool bFlagReverse
= false, LPCTSTR pszLocalBoundAddress = nullptr)
const
Return Value
If the function succeeds, the return value is true. If the function
fails, the return value is false. To get extended error information, call ::GetLastError.
Parameters
pszHostName The network address of the socket to connect to: a machine
name such as “www.somedomain.com”, or a dotted number such as “128.56.22.8” will both
work.
pr This is a reference to a structure which will be filled in upon successful
return of this function. Currently it contains:
Address This is the IP address
of the replier
RTT This is the round trip time
in Milliseconds
EchoReplyStatus The status value from the ping
Reply Contains the raw ICMP_ECHO_REPLY / ICMPV6_ECHO_REPLY structure
representing the ICMP echo reply
dwTimeout This is the timeout to use for connections in milliseconds.
nTTL This is the time to live of the ICMP packet to be sent. For those
unfamiliar with the low level details of IP, this is the maximum number of routers
through which this packet should travel. Each time an IP packet goes through a router,
its TTL value is decremented by 1. Eventually when a packet is received with a TTL
of 1, it is not forwarded and instead an ICMP reply is generated. This prevents
the network from becoming flooded with old IP packets. As an aside this is the basis
of how traceroute is implemented.
wDataSize This is the size of the data to transmit in the ICMP packet.
nTOS The Type of Service IP header field to use
bDontFragment Sets the Don't fragment IP header field
bFlagReverse Sets the Flag Reverse IP header field
pszLocalBoundAddress The local address to bind the request to
Remarks
Internally these functions will use the Iphlpapi dll to do a ping. The "v4"
method supports a IPv4 ping while the "v6" method will do a IPv6 ping.
Contacting the Author
PJ Naughter
Email: pjna@naughter.com
Web: http://www.naughter.com
18 March 2022