An ICMP Class For MFC
CIcmp - An ICMP Class For MFC
-
ICMP (Internet Control Message Protocol) messages are normally sent from destination
hosts and gateways to a source host to report problems with the Internet. While not
designed to make the Internet Protocol absolutely reliable, these control messages
can provide feedback about problems with the Internet communication environment.
ICMP messages report errors in the processing of datagrams, but should not report errors in received ICMP messages (i.e. - No ICMP messages are sent about ICMP messages). Also, ICMP messages are only sent regarding fragment zero datagrams.
ICMP messages are an integral part of the Internet Protocol, and are designed to immediately follow the IP header fields of an Internet datagram.
ICMP defines the following message types:
| Message Number | Message Type | Meaning |
|---|---|---|
| 0 | Echo Reply | Reply to Echo Request |
| 3 | Destination Unreachable | Network or Host unknown |
| 4 | Source Quench | Message too long or arrived too soon |
| 5 | Redirect | The host can be reached through a different gateway |
| 8 | Echo Request | Requests gateway/host to return sent data |
| 11 | Time Exceeded | TTL exceeded |
| 12 | Parameter Problem | Bad parameter in message header |
| 13 | Timestamp | Requests gateway/host time in mSec |
| 14 | Timestamp Reply | Gateway/host time in mSec |
| 15 | Information Request | Request host network number |
| 16 | Information Reply | Host network number |
CIcmp Class Requirements
This version of the CIcmp class implements only the Echo Request
message definition of RFC792. Refer to RFC792 - Internet Control Message
Protocol, DARPA Internet Program, Protocol Specification for details.
The CIcmp class can be easily expanded to support the complete RFC792
specification.
CloseIcmpSocket
BOOL OpenNewSocket
hWnd is a handle (GetSafeHwnd) to the window containing the
message processor which will process the asynchronous
socket events, NotificationMessage is the user-defined message number
to associate with socket events, and NotifyEvents is the mask giving the events to process.
Sets icmpSocketError and icmpSocketErrorMod to indicate the type
of error, and returns TRUE if successful, else FALSE.
icmpSocketError and icmpSocketErrorMod are preserved until the next
operation on this CIcmp object is performed.
BOOL Connect
BOOL Connect
ReceiveTimeout and SendTimeout specifies the receive
and transmit timeouts.
Sets icmpSocketError and icmpSocketErrorMod to indicate the type
of error, and returns TRUE if successful, else FALSE.
icmpSocketError and icmpSocketErrorMod are preserved until the next
operation on this CIcmp object is performed.
int CloseIcmpSocket(void)
Sets icmpSocketError and icmpSocketErrorMod to
indicate the type
of error, and returns the integer result of the operation.
icmpSocketError and icmpSocketErrorMod are
preserved until the next
operation on this CIcmp object is performed.
int SetAsynchNotification
Message is the message number to send to the window,
and Events is the event mask to notify on.
Sets icmpSocketError and icmpSocketErrorMod to
indicate the type
of error, and returns the integer result of the operation.
icmpSocketError and icmpSocketErrorMod
are preserved until the next
operation on this CIcmp object is performed.
int SetTTL (int TTL)
Since each gateway encountered along the trip to the specified host
decrements the TTL value by 1, TTL specifies the number of hops (gateways)
to query before a response is returned. By incrementing the TTL from 1 to
(number of hops to final destination), a TraceRoute function
can be performed. In order to reach a designated host, TTL must be at
least the number of gateways encountered on the way to the host, plus 1
(for the host itself).
Sets icmpSocketError and icmpSocketErrorMod to
indicate the type of error, and returns the integer result of the
operation.
icmpSocketError and icmpSocketErrorMod are
preserved until the next operation on this CIcmp object is performed.
int Ping (LPSTR pIcmpBuffer, int IcmpBufferSize)
The CIcmp variable icmpPingSentAt is set to the time value at the
time the ping message is sent.
Sets icmpSocketError and icmpSocketErrorMod to indicate the type
of error, and returns the integer result of the operation.
icmpSocketError and icmpSocketErrorMod are preserved until the next
operation on this CIcmp object is performed.
unsigned short IcmpChecksum (unsigned short FAR *lpBuf, int Len)
Returns an unsigned integer value of the computed checksum.
unsigned long GetIPAddress (LPSTR iHostName)
Sets iHostName to the value of the host name returned in
icmpHostEnt.
Requires the message number to send to the window, and the events
to notify on.
Sets CIcmp variable icmpSockAddr fields appropriately,
leaving the IP address in icmpSockAddr.sin_addr, and the
type of address in
icmpSockAddr.sin_family. Also sets icmpHostEnt fields appropriately
Sets icmpSocketError and icmpSocketErrorMod to indicate the type
of error, and returns the integer result of the operation.
icmpSocketError and icmpSocketErrorMod are preserved until the next
operation on this CIcmp object is performed.
int Receive (LPSTR pIcmpBuffer, int IcmpBufferSize)
pIcmpBuffer is the address of the buffer to store the incoming message
and IcmpBufferSize is the integer buffer size. The buffer must be large
enough to contain the incoming message. In the case of an ICMP Echo
Reply, the size would be the size of the outgoing message plus
the size of an ICMP header plus the size of an IP header.
Sets icmpRcvLen to the length of the message received,
icmpPingReceivedAt to the time the receive command is issued,
icmpRoundTripTime to the difference between icmpPingSentAt
and icmpPingReceivedAt, icmpCurSeq to the incoming
sequence number and icmpCurId to the incoming id field.
Sets rcvSockAddr fields appropriately.
Sets icmpSocketError and icmpSocketErrorMod to indicate the type
of error, and returns the integer result of the operation.
icmpSocketError and icmpSocketErrorMod are preserved until the next
operation on this CIcmp object is performed.
void DisplayError (CString ErrorType, CString FunctionName)
Sets the message box title to FunctionName.
The message is displayed in a modal box, requiring an OK response
before the thread containing this method can progress.
The CIcmp class contains the following public variables:
The CIcmp class, derived from the MFC CSocket class,
was developed to fill the requirement for class-based access to RAW
sockets to perform ICMP echo
requests. This class was designed using Microsoft's VisualC++ version 4.2 and
MFC, and was tested on both a WindowsNT 4.0 Workstation and Server using
WindowsNT Winsock 2. Because of its reliance upon WindowsNT Winsock 2 structures,
it will not work on Windows95. A version which will work with Windows95 will be
available soon.
The CIcmp class provides the following methods for WindowsNT 4.0 systems utilizing the WindowsNT Winsock 2 interface to the Internet:
Connect
DisplayError
GetIPAddress
IcmpChecksum
OpenNewSocket
Ping
Receive
SetAsynchNotification
SetTTL
BOOL OpenNewSocket
(HWND hWnd,
unsigned int NotificationMessage,
long NotifyEvents)
(HWND hWnd,
unsigned int NotificationMessage,
long NotifyEvents,
int AFamily,
int AType,
int AProtocol)
Opens a SOCKET of type AType belonging to family
AFamily and with protocol AProtocol.
If AFamily, AType and AProtocol are not provided, opens
a SOCKET connection to a RAW socket with ICMP protocol.
(LPINT ReceiveTimeout,
LPINT SendTimeout)
(LPINT ReceiveTimeout,
LPINT SendTimeout,
int AFamily,
int AType,
int AProtocol)
Connects a CIcmp object to a socket
of specified family (AFamily), type (AType) and
protocol (AProtocol). If AFamily, AType
and AProtocol are not provided, connects a CIcmp
object to a RAW socket with ICMP protocol.
Closes a socket associated with a CIcmp object.
(HWND hWnd,
unsigned int Message,
long Events)
Sets the window (process) to notify when a network event on the
socket associated with the CIcmp object occurs.
Set the TTL (Time-To-Live) option on the socket associated with a
CIcmp object. The TTL value specifies the number of seconds
an Internet datagram is to exist.
Sends an ICMP Echo Request (ping) message to the host indicated
in the CIcmp
variable icmpSockAddr. The CIcmp variables
icmpCurSeq and
icmpCurId are sent in the buffer referenced by pIcmpBuffer. The
referenced buffer must be large enough to hold DataLen bytes plus
the size of the ICMP message header.
Computes the ICMP checksum of the data in the buffer referenced
by lpBuf for Len bytes.
Returns the value of the IP address of the host pointed by
iHostName as an unsigned long in network byte order, as described
in inet_aton.
Reads the socket associated with the CIcmp object and returns the
number of bytes read, or SOCKET_ERROR, if an error occurs.
Displays the provided ErrorType message prior to the decoded error
message in icmpSocketError and icmpSocketErrorMod.
icmpCurId
icmpCurSeq
icmpHops
icmpHostAddress
icmpMaxHops
icmpPingReceivedAt
icmpPingSentAt
icmpRcvLen
icmpRoundTripTime
icmpSockAddr
icmpSocket
icmpPingTimer
icmpSocketError
icmpSocketErrorMod
pIcmpHeader
pIpHeader
rcvSockAddr
- Pointer to an IcmpHeader structure;
- Usually mapped to the current ICMP buffer.
- Pointer to an IpHeader structure;
- Usually mapped to the current receive buffer.
- An asynchronous socket. See CSocket class for implementation;
- Contains the current socket for this CIcmp object;
- Default is INVALID_SOCKET for unopened/unassigned socket.
- Socket address structure for outgoing (send) socket communication;
- Refer to SOCKADDR_IN structure in VisualC++ help or MFC documentation.
- Socket address structure for incoming (recvfrom) socket communication;
- Refer to SOCKADDR_IN structure in VisualC++ help or MFC documentation.
- Time between sending a message and receiving the echo;
- in mSec.
- Host address in network byte order;
- Maintained external to the CIcmp class;
- see inet_aton for format.
- System time when the last ICMP message was sent;
- in mSec.
- System time when the last ICMP message was received;
- in mSec.
- integer length of the last message received;
- set by Receive.
- Number of hops (routers contacted) in a trace route operation;
- Set to zero by Connect method;
- Maintained external to class (by application program).
- A limit set for trace route operations which fail to complete gracefully;
- Defaults to 30 in the CIcmp constructor;
- Maintained external to class (by application program).
- Current ICMP message sequence number;
- Set by application program before calling Ping;
- Set by Receive after processing an incoming (recvfrom) message.
- ICMP id field;
- Set to current process id by Connect;
- Assigned to outgoing ICMP message by Ping;
- Set to incoming ICMP id field by Receive
- send (Ping) timeout in mSec;
- recvfrom (Receive) timeout in mSec.
- The WSAGetLastError for the last error which occurred;
- Preserved until the next socket error occurs.
- The entry level in the processing routine at which icmpSocketError occurred;
- Preserved until the next socket error occurs.
-
To use this class,
- Copy the files Icmp.cpp, Icmp.h and Icmp.rc to the same directory as your project;
- Include Icmp.cpp and Icmp.rc in your project. This will cause an error notification that only one .rc file can be active...ignore it, the following steps will fix it;
- Open the file Icmp.rc, select the string table, and highlight all of the messages;
- Copy the resource strings to the clipboard (copy button);
- Open the projects' string table and paste the strings into the next available slot (paste button);
- Close both string tables and remove (delete) the file Icmp.rc from your project;
- Add Icmp.h to any modules in which you make reference to CIcmp
or one
of its' methods or variables. This will normally take the form of
-
#include "Icmp.h"
EWDPing - A Demonstration of the CIcmp Class
-
EWDPing is a sample program which illustrates the use of the CIcmp class.
- CIcmp
- An object class derived from the MFC CSocket object class to provide access to RAW sockets and ICMP (Internet Control Message Protocol) functions.
- CRegKey
- An object class to provide to WindowsNT/95 system registry objects.
- CSysTCPIP
- An object class to provide access to some of the TCP/IP related information stored in the system registry on Windows NT using Microsoft's Winsock 2 interface.
This program implements the ICMP Echo Request message (commonly known as PING) to check the on-line status of an Internet host, and uses TTL to trace the route to an Internet host.
The .zip file contains the source for EWDPing as well as the source for the other custom classes used in the project:
The program also makes use of a system timer to prevent "hanging" on a non-responsive gateway.
Documentation for the methods and variables are provided within the .zip file.

Comments
Problem with tracing the back route
Posted by Legacy on 04/15/2002 12:00amOriginally posted by: Czereova
Don't you know, how to trace the back route ?
ReplyI call the function lpfnIcmpSendEcho just till I reach the destination address and thats it. But i need to compare the route to the destination and route back from the destination to the source. Thanks.
setsockopt error..help needed
Posted by Legacy on 03/19/2002 12:00amOriginally posted by: nmnat
I do have similar problem what Tommaso Trani has posted.. how to solve this problem?
Thanks.
ReplyWhy Cannot Bind,Help?
Posted by Legacy on 09/24/2001 12:00amOriginally posted by: Ksek Qiu
If the operater is not a aministrator(NT),the socket cannot bind to the icmp protocol,who can tell me why?
Replythanks for you help!!
Re: Problems with compilation
Posted by Legacy on 04/18/2001 12:00amOriginally posted by: Efran Cobisi
If you got errors from the compilation (eg infamous 65 errors), just add the following line to "icmp.h" head:
#include <afxsock.h>
It simply enables MFC WinSock support, letting all work ok!
Efran Cobisi, sercom S.r.l.
ReplyProblems running EWDPing progarm on Windows NT 4.00.1381 machines
Posted by Legacy on 01/05/2001 12:00amOriginally posted by: April Luk
Hi Jay,
I've tried to run the demo program on a Windows NT 4.00.1381 machines but failed. I didn't modified anything. The error I got is:
CEWDPingDlg::InitSockets
WSA_PING_ASYNC Error (10013-1) : WSACCESS: Permission denied
I've ran the demo program on a Windows 98, 98SE and 95 machines and it was working fine. I would like to know do you have any idea is going wrong? Do I need any special previleges in order to get the program working?
I've tried to access the webpage http://www.earthwalkerdesigns.com
to try to search for an update version but that webpage does not exist.
I'm actually using your class for my university project and this problem is actually now holding up my project development. Can you please kindly advise as soon as possible? You can email me directly. Thanks!
Regards,
ReplyApril
Excellent
Posted by Legacy on 08/23/2000 12:00amOriginally posted by: jon howell
A very good and handly class!
ReplyGot Demo to work
Posted by Legacy on 05/13/2000 12:00amOriginally posted by: Thane
I ran into problems create the project at first, then decided to open the .mak file through Visual Studio 6.0. I didn't seem an option for .mak files so I decide to use the option All files and opened the .mak file. This was on an NT 4.0 system.
Visual Studio prompt me, asking if I would like to upgrade the project to Visual Studio 6.0 and it coverted the files and created the correct .dsw file and then I buildt the program in debug mode no special settings and ran the program it worked fine.
TDG
ReplyProblem compiling (65 errors!)
Posted by Legacy on 02/04/2000 12:00amOriginally posted by: Chris
I ran into some problems compiling. When I run through your setup steps, and I get
65 compilation errors. The first being
f:\proj1\icmp.h(234) : error C2143: syntax error : missing ';' before '*'
#pragma pack (4)
//////////////////////////////////////////////////////////////////
//
//
//
//
//////////////////////////////////////////////////////////////////
#define MAXBFRSIZE 2048
#define MAX_HOPS 30
typedef SOCKET * LPSOCKET; <---- Line 234
I know I'm probably forgetting to include something. I've been trying to implement some icmp functions over the past few days, and have had issues get visual studio to see these functions. I'm using VC++ 6. All I've done is follow your steps, nothing else.
-Thanks
Chris
ReplyProblem calling setsockopt
Posted by Legacy on 12/01/1999 12:00amOriginally posted by: Tommaso Trani
Can you tell me why the call setsockopt return SOCKET_ERROR?
Result = setsockopt (icmpSocket, IPPROTO_IP, IP_TTL, (LPSTR)&TTL, sizeof(int));
I've Inserted EwdPing (I've replaced the application class) in a my project, and I've not modified anything! Your sample work, but mine not.
Ehm.. I've only modified the position of #include <afxsock.h>; if I insert it in stdafx.h I've a lot of error of redefinition, so I've inserted itto the .cpp files.
I've the fail in void CEWDPingDlg::SendPing(void)
when calling SetTTL.
if (PingSocket.SetTTL (icmpPingTTL) == SOCKET_ERROR)
...
I've seen that the parameter icmpPingTTL passed to this function is the same as in my program as in your sample.
If I go deeper (with Debug) and I trace SetTTL, I've seen that the first parameter passed to setsockopt (icmpSocket), in my program has always the value 48, but in your sample is 24.
At this point I've tried to modify manually the call to setsockopt passing 24 as first parameter:
icmpSocket=24;
Result = setsockopt (icmpSocket, IPPROTO_IP, IP_TTL, (LPSTR)&TTL, sizeof(int));
But this don't work again!
At this point I think there is same error into the initialization of object CIcmp, but I can't have seen any difference with your app.
Can you help me?
If you can, can you eMail me the solution?
Thanks in advance,
Tommaso.
ReplyP.S. If you want I can send you my app (I cut all is not needed).
Icmp Class
Posted by Legacy on 11/18/1998 12:00amOriginally posted by: Minh Do
Hi Jay,
My name is Minh Do, and i am new to Windows development.
I have mostly written applications in Unix.
I am familiar with icmp issues. One of the technique
that is being used to discover devices in a subnetwork is
sending a ping sweep. A regular ping command is sent
to a broacast address, and the ping program listens on the
socket for reply.
On a Solaris machine, the command is:
Ex: ping -s 134.177.189.0
There should be many response returned.
Of course, if running the above command in Windows, it does
not work. Since the ping program explicitly tries to open
address 134.177.189.0, and when it gets the response from
the recvfrom, if the address does not match with the
sending
In my unix application, I control the replies using a select
statement:
Example code:
// Format icmp packet
// Send a ping message
sendto = sendto (socket, (char *) packet, packetlen, 0,
&whereto, sizeof (struct sockaddr));
while (1) {
numfds = 0; // reset the number of file descriptors
FD_ZERO (&fdset);
block = 0; // Set to block
timerclear (&timeout); // Reset timeout
// Check if there are any ping sent pending.
// If we sent a ping, then this value is at least 1
numping = pingSelectInfo (&numfds, &fds, tvp, &block);
if (! numping) break;
tvp = &timeout;
if (block == 1) tvp = NULL; // Block with out timeout
count = select (numfds, &fdset, 0, 0, tvp);
if (count > 0) {
pingRead (&fdset);
}
else {
switch (count) { // Count can only be 0 or negative
case 0:
// Timeout. Send more packet if this is the case
if (! ipPingTimeOut ()) return;
break;
case -1:
printf ("ERROR");
default:
return; // Exit out of the function
}
}
}
I also notice that standard header icmp structure does not
match with the Berkley icmp structure. I have changed my internal
icmp structure to match with Microsft structure to no prevail.
I have look at example of Windows ping using select statement,
but could not find one that works. They all adhere to the ping
example MSFT gives in the SDK.
Format the cmp packet
Do a sendto
Do a recvfrom
Note that, I have been able to port my other code in Unix to
Windows to do snmp using socket and select statements.
I was able to collect snmp information. I ran purify, and
nothing is out of the ordinary.
So all the winsocket calls and setups are correct.
I just want to mention the problem here, in case anybody have run
into the problem before, and have a solution for it.
If a ping broadcast message cannot be sent, then it would take
a long time to discover devices in a network.
I am waiting to get a hand on a sniffer, and intend to see what
are the packets that are coming back after a ping message.
Thanks,
- Minh Do
ReplyLoading, Please Wait ...