icmp.cxx
上传用户:hzhsqp
上传日期:2007-01-06
资源大小:1600k
文件大小:9k
源码类别:

IP电话/视频会议

开发平台:

Visual C++

  1. /*
  2.  * icmp.cxx
  3.  *
  4.  * ICMP class implementation for Win32.
  5.  *
  6.  * Portable Windows Library
  7.  *
  8.  * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
  9.  *
  10.  * The contents of this file are subject to the Mozilla Public License
  11.  * Version 1.0 (the "License"); you may not use this file except in
  12.  * compliance with the License. You may obtain a copy of the License at
  13.  * http://www.mozilla.org/MPL/
  14.  *
  15.  * Software distributed under the License is distributed on an "AS IS"
  16.  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  17.  * the License for the specific language governing rights and limitations
  18.  * under the License.
  19.  *
  20.  * The Original Code is Portable Windows Library.
  21.  *
  22.  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
  23.  *
  24.  * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
  25.  * All Rights Reserved.
  26.  *
  27.  * Contributor(s): ______________________________________.
  28.  *
  29.  * $Log: icmp.cxx,v $
  30.  * Revision 1.13  1999/08/08 09:29:37  robertj
  31.  * Changed Success to PingSuccess to avoid namespace collision with X define of the same name
  32.  *
  33.  * Revision 1.12  1999/02/16 08:08:06  robertj
  34.  * MSVC 6.0 compatibility changes.
  35.  *
  36.  * Revision 1.11  1998/11/30 04:48:39  robertj
  37.  * New directory structure
  38.  *
  39.  * Revision 1.10  1998/09/24 03:30:46  robertj
  40.  * Added open software license.
  41.  *
  42.  * Revision 1.9  1998/01/26 00:53:33  robertj
  43.  * Added error codes, TTL and data buffer to Ping.
  44.  *
  45.  * Revision 1.8  1997/10/03 13:32:46  robertj
  46.  * Changed to late binding so do not need icmp.lib to compile system.
  47.  *
  48.  * Revision 1.7  1996/10/29 13:27:17  robertj
  49.  * Change ICMP to use DLL rather than Winsock
  50.  *
  51.  */
  52. #include <ptlib.h>
  53. #include <ptlib/sockets.h>
  54. ///////////////////////////////////////////////////////////////
  55. //
  56. // Definitions for Microsft ICMP library
  57. //
  58. // return values from IcmpSendEcho
  59. #define IP_STATUS_BASE 11000
  60. #define IP_SUCCESS 0
  61. #define IP_BUF_TOO_SMALL (IP_STATUS_BASE + 1)
  62. #define IP_DEST_NET_UNREACHABLE (IP_STATUS_BASE + 2)
  63. #define IP_DEST_HOST_UNREACHABLE (IP_STATUS_BASE + 3)
  64. #define IP_DEST_PROT_UNREACHABLE (IP_STATUS_BASE + 4)
  65. #define IP_DEST_PORT_UNREACHABLE (IP_STATUS_BASE + 5)
  66. #define IP_NO_RESOURCES (IP_STATUS_BASE + 6)
  67. #define IP_BAD_OPTION (IP_STATUS_BASE + 7)
  68. #define IP_HW_ERROR (IP_STATUS_BASE + 8)
  69. #define IP_PACKET_TOO_BIG (IP_STATUS_BASE + 9)
  70. #define IP_REQ_TIMED_OUT (IP_STATUS_BASE + 10)
  71. #define IP_BAD_REQ (IP_STATUS_BASE + 11)
  72. #define IP_BAD_ROUTE (IP_STATUS_BASE + 12)
  73. #define IP_TTL_EXPIRED_TRANSIT (IP_STATUS_BASE + 13)
  74. #define IP_TTL_EXPIRED_REASSEM (IP_STATUS_BASE + 14)
  75. #define IP_PARAM_PROBLEM (IP_STATUS_BASE + 15)
  76. #define IP_SOURCE_QUENCH (IP_STATUS_BASE + 16)
  77. #define IP_OPTION_TOO_BIG (IP_STATUS_BASE + 17)
  78. #define IP_BAD_DESTINATION (IP_STATUS_BASE + 18)
  79. #define IP_ADDR_DELETED (IP_STATUS_BASE + 19)
  80. #define IP_SPEC_MTU_CHANGE (IP_STATUS_BASE + 20)
  81. #define IP_MTU_CHANGE (IP_STATUS_BASE + 21)
  82. #define IP_UNLOAD (IP_STATUS_BASE + 22)
  83. #define IP_GENERAL_FAILURE (IP_STATUS_BASE + 50)
  84. #define MAX_IP_STATUS IP_GENERAL_FAILURE
  85. #define IP_PENDING (IP_STATUS_BASE + 255)
  86. // ICMP request options structure
  87. typedef struct ip_info {
  88.      u_char Ttl;               /* Time To Live (used for traceroute) */
  89.      u_char Tos;               /* Type Of Service (usually 0) */
  90.      u_char Flags;             /* IP header flags (usually 0) */
  91.      u_char OptionsSize;       /* Size of options data (usually 0, max 40) */
  92.      u_char FAR *OptionsData;  /* Options data buffer */
  93. } IPINFO;
  94. //
  95. // ICMP reply data
  96. //
  97. // The reply buffer will have an array of ICMP_ECHO_REPLY
  98. // structures, followed by options and the data in ICMP echo reply
  99. // datagram received. You must have room for at least one ICMP
  100. // echo reply structure, plus 8 bytes for an ICMP header.
  101. // 
  102. typedef struct icmp_echo_reply {
  103.      u_long Address;         /* source address */
  104.      u_long Status;          /* IP status value (see below) */
  105.      u_long RTTime;          /* Round Trip Time in milliseconds */
  106.      u_short DataSize;       /* reply data size */
  107.      u_short Reserved;    
  108.      void FAR *Data;         /* reply data buffer */
  109.      struct ip_info Options; /* reply options */
  110. } ICMPECHO;
  111. class PICMPDLL : public PDynaLink
  112. {
  113.   PCLASSINFO(PICMPDLL, PDynaLink)
  114.   public:
  115.     PICMPDLL()
  116.       : PDynaLink("ICMP.DLL")
  117.     {
  118.       if (!GetFunction("IcmpCreateFile", (Function &)IcmpCreateFile) ||
  119.   !GetFunction("IcmpCloseHandle", (Function &)IcmpCloseHandle) ||
  120.   !GetFunction("IcmpSendEcho", (Function &)IcmpSendEcho))
  121. Close();
  122.     }
  123.     // create an ICMP "handle"
  124.     // returns INVALID_HANDLE_VALUE on error 
  125.     HANDLE (WINAPI *IcmpCreateFile)(void);
  126.     // close a handle allocated by IcmpCreateFile
  127.     // returns FALSE on error
  128.     BOOL (PASCAL *IcmpCloseHandle)(HANDLE handle);
  129.     // Send the ICMP echo command for a "ping"
  130.     DWORD (PASCAL *IcmpSendEcho)(
  131.  HANDLE   handle,           /* handle returned from IcmpCreateFile() */
  132.  u_long   destAddr,         /* destination IP address (in network order) */
  133.  void   * sendBuffer,       /* pointer to buffer to send */
  134.  WORD     sendLength,       /* length of data in buffer */
  135.  IPINFO * requestOptions,   /* see structure definition above */
  136.  void   * replyBuffer,      /* structure definitionm above */
  137.  DWORD    replySize,        /* size of reply buffer */
  138.  DWORD    timeout           /* time in milliseconds to wait for reply */
  139.     );
  140. } ICMP;
  141. PICMPSocket::PICMPSocket()
  142. {
  143.   OpenSocket();
  144. }
  145. BOOL PICMPSocket::IsOpen() const
  146. {
  147.   return icmpHandle != NULL;
  148. }
  149. BOOL PICMPSocket::OpenSocket()
  150. {
  151.   return ICMP.IsLoaded() && (icmpHandle = ICMP.IcmpCreateFile()) != NULL;
  152. }
  153. BOOL PICMPSocket::Close()
  154. {
  155.   if (icmpHandle == NULL) 
  156.     return TRUE;
  157.   PAssert(ICMP.IsLoaded(), PLogicError);
  158.   return ICMP.IcmpCloseHandle(icmpHandle);
  159. }
  160. const char * PICMPSocket::GetProtocolName() const
  161. {
  162.   return "icmp";
  163. }
  164. BOOL PICMPSocket::Ping(const PString & host)
  165. {
  166.   PingInfo info;
  167.   return Ping(host, info);
  168. }
  169. BOOL PICMPSocket::Ping(const PString & host, PingInfo & info)
  170. {
  171.   if (!ICMP.IsLoaded()) {
  172.     lastError = NotOpen;
  173.     return FALSE;
  174.   }
  175.   // find address of the host
  176.   PIPSocket::Address addr;
  177.   if (!GetHostAddress(host, addr)) {
  178.     lastError = BadParameter;
  179.     return FALSE;
  180.   }
  181.   IPINFO requestOptions;
  182.   requestOptions.Ttl = info.ttl;     /* Time To Live (used for traceroute) */
  183.   requestOptions.Tos = 0;            /* Type Of Service (usually 0) */
  184.   requestOptions.Flags = 0;          /* IP header flags (usually 0) */
  185.   requestOptions.OptionsSize = 0;    /* Size of options data (usually 0, max 40) */
  186.   requestOptions.OptionsData = NULL; /* Options data buffer */
  187.   BYTE sendBuffer[32];
  188.   void * sendBufferPtr;
  189.   WORD sendBufferSize;
  190.   if (info.buffer != NULL) {
  191.     sendBufferPtr = (void *)info.buffer;
  192.     PAssert(info.bufferSize < 65535, PInvalidParameter);
  193.     sendBufferSize = (WORD)info.bufferSize;
  194.   }
  195.   else {
  196.     sendBufferPtr = sendBuffer;
  197.     sendBufferSize = sizeof(sendBuffer);
  198.   }
  199.   ICMPECHO * reply = (ICMPECHO *)malloc(sizeof(ICMPECHO)+sendBufferSize);
  200.   if (ICMP.IcmpSendEcho(icmpHandle,
  201.         addr,
  202.         sendBufferPtr, sendBufferSize,
  203.         &requestOptions,
  204.         reply, sizeof(ICMPECHO)+sendBufferSize,
  205.         GetReadTimeout().GetInterval()) != 0) {
  206.     info.delay.SetInterval(reply->RTTime);
  207.     info.remoteAddr = Address((in_addr&)reply->Address);
  208.   }
  209.   GetHostAddress(info.localAddr);
  210.   switch (reply->Status) {
  211.     case IP_SUCCESS :
  212.       info.status = PingSuccess;
  213.       break;
  214.     case IP_DEST_NET_UNREACHABLE :
  215.       info.status = NetworkUnreachable;
  216.       break;
  217.     case IP_DEST_HOST_UNREACHABLE :
  218.       info.status = HostUnreachable;
  219.       break;
  220.     case IP_PACKET_TOO_BIG :
  221.       info.status = PacketTooBig;
  222.       break;
  223.     case IP_REQ_TIMED_OUT :
  224.       info.status = RequestTimedOut;
  225.       break;
  226.     case IP_BAD_ROUTE :
  227.       info.status = BadRoute;
  228.       break;
  229.     case IP_TTL_EXPIRED_TRANSIT :
  230.       info.status = TtlExpiredTransmit;
  231.       break;
  232.     case IP_TTL_EXPIRED_REASSEM :
  233.       info.status = TtlExpiredReassembly;
  234.       break;
  235.     case IP_SOURCE_QUENCH :
  236.       info.status = SourceQuench;
  237.       break;
  238.     case IP_MTU_CHANGE :
  239.       info.status = MtuChange;
  240.       break;
  241.     default :
  242.       info.status = GeneralError;
  243.   }
  244.   free(reply);
  245.   return info.status == PingSuccess;
  246. }
  247. PICMPSocket::PingInfo::PingInfo(WORD id)
  248. {
  249.   identifier = id;
  250.   sequenceNum = 0;
  251.   ttl = 255;
  252.   buffer = NULL;
  253.   status = PingSuccess;
  254. }
  255. // End Of File ///////////////////////////////////////////////////////////////