An ICMP Class For MFC


CIcmp - An ICMP Class For MFC


Overview of ICMP
    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


Class Methods


    BOOL OpenNewSocket
      (HWND hWnd,
      unsigned int NotificationMessage,
      long NotifyEvents)

    BOOL OpenNewSocket

      (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.

      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

      (LPINT ReceiveTimeout,
      LPINT SendTimeout)

    BOOL Connect

      (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.

      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)

      Closes a socket associated with a CIcmp object.

      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

      (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.

      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)

      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.

      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)

      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.

      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)

      Computes the ICMP checksum of the data in the buffer referenced by lpBuf for Len bytes.

      Returns an unsigned integer value of the computed checksum.


    unsigned long GetIPAddress (LPSTR iHostName)

      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.

      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)

      Reads the socket associated with the CIcmp object and returns the number of bytes read, or SOCKET_ERROR, if an error occurs.

      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)

      Displays the provided ErrorType message prior to the decoded error message in icmpSocketError and icmpSocketErrorMod.

      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.


Class Variables

The CIcmp class contains the following public variables:


LPIcmpHeader pIcmpHeader
  • Pointer to an IcmpHeader structure;
  • Usually mapped to the current ICMP buffer.

LPIpHeader pIpHeader
  • Pointer to an IpHeader structure;
  • Usually mapped to the current receive buffer.

SOCKET icmpSocket
  • An asynchronous socket. See CSocket class for implementation;
  • Contains the current socket for this CIcmp object;
  • Default is INVALID_SOCKET for unopened/unassigned socket.

SOCKADDR_IN icmpSockAddr
  • Socket address structure for outgoing (send) socket communication;
  • Refer to SOCKADDR_IN structure in VisualC++ help or MFC documentation.

SOCKADDR_IN rcvSockAddr
  • Socket address structure for incoming (recvfrom) socket communication;
  • Refer to SOCKADDR_IN structure in VisualC++ help or MFC documentation.

DWORD icmpRoundTripTime
  • Time between sending a message and receiving the echo;
  • in mSec.

unsigned long icmpHostAddress
  • Host address in network byte order;
  • Maintained external to the CIcmp class;
  • see inet_aton for format.

DWORD icmpPingSentAt
  • System time when the last ICMP message was sent;
  • in mSec.

DWORD icmpPingReceivedAt
  • System time when the last ICMP message was received;
  • in mSec.

int icmpRcvLen
  • integer length of the last message received;
  • set by Receive.

int icmpHops
  • Number of hops (routers contacted) in a trace route operation;
  • Set to zero by Connect method;
  • Maintained external to class (by application program).

int icmpMaxHops
  • 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).

int icmpCurSeq
  • Current ICMP message sequence number;
  • Set by application program before calling Ping;
  • Set by Receive after processing an incoming (recvfrom) message.

int icmpCurId
  • 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

int icmpPingTimer
  • send (Ping) timeout in mSec;
  • recvfrom (Receive) timeout in mSec.

int icmpSocketError
  • The WSAGetLastError for the last error which occurred;
  • Preserved until the next socket error occurs.

int icmpSocketErrorMod
  • The entry level in the processing routine at which icmpSocketError occurred;
  • Preserved until the next socket error occurs.


Installing the Class

    To use this class,
    1. Copy the files Icmp.cpp, Icmp.h and Icmp.rc to the same directory as your project;
    2. 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;
    3. Open the file Icmp.rc, select the string table, and highlight all of the messages;
    4. Copy the resource strings to the clipboard (copy button);
    5. Open the projects' string table and paste the strings into the next available slot (paste button);
    6. Close both string tables and remove (delete) the file Icmp.rc from your project;
    7. 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"
      in the header files in which the CIcmp object is declared.


EWDPing - A Demonstration of the CIcmp Class

    EWDPing is a sample program which illustrates the use of the CIcmp class.

    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:

      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.

    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.

Download demo project - 151KB
Download source - 26KB



Comments

  • How to use the file Icmp.h and Icmp.cpp

    Posted by Legacy on 04/02/2002 12:00am

    Originally posted by: Tom

    Dear sir,
    I am a student and work for a project about server managemant recently. I have some problem about using your class CIcmp, which is downloaded from the following link:
    http://www.codeguru.com/internet/cicmp.shtml

    I understand how to add the file "Icmp.h" and "Icmp.cpp" into my project, but I don't know how to use the functions. Actually, I just need to ping whether a server is active periodically, I do not need to use any functionality about traceroute. I want to ask what should be the proper sequence to call the functions you provided. Please help me when you have time. Thanks a lot.

    Regards,
    Tom

    Reply
  • Problems, Problems: Demo works only with user having admin rights...

    Posted by Legacy on 06/17/1999 12:00am

    Originally posted by: Marcus

    Hello,

    after a long search I found this demo and tried it but I have some problems:

    The demo works only under a user being a member of the admins group. A normal user under NT brings up the following error message:

    "WSA_PING_ASYNC Error (10013-1):
    WSACCESS: Permission denied"

    I'm not so into winsock programming and I need only to ping another pc from my prog, but it's not possible to run that app under admin rights.

    So how can I solve that? Any ideas?

    TNX

    Marcus

    Reply
  • Praises

    Posted by Legacy on 06/17/1999 12:00am

    Originally posted by: Daniel W. Mathiasen

    Hi,
    
    

    Its a very well written article, above the normal of codeguru, which isn't bad at all either.

    Good work,

    Daniel W. Mathiasen

    Reply
  • Icmp Class

    Posted by Legacy on 11/18/1998 12:00am

    Originally 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

    Reply
  • Winsock 2 on Win 95

    Posted by Legacy on 11/17/1998 12:00am

    Originally posted by: A.V.Ramaswamy

    Microsoft has a Winsock 2 upgrade for Win 95. So, if your code works on
    NT 4.0 and requires Winsock 2, this code should work on Win 95 also
    (if you have installed the Winsock 2 upgrade).

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: December 11, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT Market pressures to move more quickly and develop innovative applications are forcing organizations to rethink how they develop and release applications. The combination of public clouds and physical back-end infrastructures are a means to get applications out faster. However, these hybrid solutions complicate DevOps adoption, with application delivery pipelines that span across complex hybrid cloud and non-cloud environments. Check out this …

  • With the average hard drive now averaging one terabyte in size, the fallout from the explosion of user-created data has become an overwhelming volume of potential evidence that law-enforcement and corporate investigators spend countless hours examining. Join Us and SANS' Rob Lee for our 45-minute webinar, A Triage and Collection Strategy for Time-Sensitive Investigations, will demonstrate how to: Identify the folders and files that often contain key insights Reduce the time spent sifting through content by …

Most Popular Programming Stories

More for Developers

RSS Feeds