Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

358 lines
8.6 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. ping.c
  5. Abstract:
  6. Packet INternet Groper utility for TCP/IP.
  7. Author:
  8. Numerous TCP/IP folks.
  9. Revision History:
  10. Who When What
  11. -------- -------- ----------------------------------------------
  12. WeihaiC 5-Dec-98. Moved from \nt\private\net\sockets\tcpcmd\ping
  13. MohsinA, 21-Oct-96. INADDR_NONE check to avoid broadcast.
  14. MohsinA, 13-Nov-96. Max packet size < 64K.
  15. Notes:
  16. --*/
  17. //:ts=4
  18. typedef unsigned long ULONG;
  19. typedef unsigned short ushort;
  20. typedef unsigned int UINT;
  21. typedef unsigned char UCHAR;
  22. #include "precomp.h"
  23. #include "icmpapi.h"
  24. #define NOGDI
  25. #define NOMINMAX
  26. #define MAX_BUFFER_SIZE (sizeof(ICMP_ECHO_REPLY) + 0xfff7 + MAX_OPT_SIZE)
  27. #define DEFAULT_BUFFER_SIZE (0x2000 - 8)
  28. #define DEFAULT_SEND_SIZE 32
  29. #define DEFAULT_COUNT 4
  30. #define DEFAULT_TTL 32
  31. #define DEFAULT_TOS 0
  32. #define DEFAULT_TIMEOUT 5000L
  33. #define MIN_INTERVAL 1000L
  34. #define TRUE 1
  35. #define FALSE 0
  36. #define STDOUT 1
  37. #define net_long(x) (((((ULONG)(x))&0xffL)<<24) | \
  38. ((((ULONG)(x))&0xff00L)<<8) | \
  39. ((((ULONG)(x))&0xff0000L)>>8) | \
  40. ((((ULONG)(x))&0xff000000L)>>24))
  41. #ifdef VXD
  42. #define FAR _far
  43. #endif // VXD
  44. WSADATA WsaData;
  45. // ========================================================================
  46. // Caveat: return 0 for invalid, else internet address.
  47. // I would prefer -1 for error. - MohsinA, 21-Nov-96.
  48. unsigned long
  49. get_pingee(char *ahstr, char **hstr, int *was_inaddr, int dnsreq)
  50. {
  51. struct hostent *hostp = NULL;
  52. long inaddr;
  53. if( strcmp( ahstr, "255.255.255.255" ) == 0 ){
  54. return 0L;
  55. }
  56. if ((inaddr = inet_addr(ahstr)) == -1L) {
  57. hostp = gethostbyname(ahstr);
  58. if (hostp) {
  59. /*
  60. * If we find a host entry, set up the internet address
  61. */
  62. inaddr = *(long *)hostp->h_addr;
  63. *was_inaddr = 0;
  64. } else {
  65. // Neither dotted, not name.
  66. return(0L);
  67. }
  68. } else {
  69. // Is dotted.
  70. *was_inaddr = 1;
  71. if (dnsreq == 1) {
  72. hostp = gethostbyaddr((char *)&inaddr,sizeof(inaddr),AF_INET);
  73. }
  74. }
  75. *hstr = hostp ? hostp->h_name : (char *)NULL;
  76. return(inaddr);
  77. }
  78. // ========================================================================
  79. BOOL Ping (LPTSTR pszServerName)
  80. {
  81. UINT i;
  82. UINT j;
  83. int found_addr = 0;
  84. int dnsreq = 0;
  85. char *hostname = NULL;
  86. int was_inaddr;
  87. DWORD numberOfReplies;
  88. UINT Count = DEFAULT_COUNT;
  89. UCHAR TTL = DEFAULT_TTL;
  90. UCHAR FAR *Opt = (UCHAR FAR *)0; // Pointer to send options
  91. UINT OptLength = 0;
  92. int OptIndex = 0; // Current index into SendOptions
  93. int SRIndex = -1; // Where to put address, if source routing
  94. UCHAR TOS = DEFAULT_TOS;
  95. UCHAR Flags = 0;
  96. ULONG Timeout = DEFAULT_TIMEOUT;
  97. IP_OPTION_INFORMATION SendOpts;
  98. int EndOffset;
  99. ULONG TempAddr;
  100. UCHAR TempCount;
  101. DWORD errorCode;
  102. HANDLE IcmpHandle = NULL;
  103. int err;
  104. struct in_addr addr;
  105. BOOL result;
  106. PICMP_ECHO_REPLY reply;
  107. BOOL sourceRouting = FALSE;
  108. char *SendBuffer = NULL;
  109. char *RcvBuffer = NULL;
  110. UINT RcvSize;
  111. UINT SendSize = DEFAULT_SEND_SIZE;
  112. BOOL bRet = FALSE;
  113. IPAddr address = 0; // was local to main earlier.
  114. char *arg;
  115. // ====================================================================
  116. #ifdef UNICODE
  117. LPSTR pszAnsiServerName = NULL;
  118. DWORD uSize;
  119. if (pszServerName && (uSize = WideCharToMultiByte(CP_ACP,
  120. 0,
  121. pszServerName,
  122. -1,
  123. NULL,
  124. 0,
  125. NULL,
  126. NULL))) {
  127. if (pszAnsiServerName = (LPSTR) LocalAlloc(LPTR, uSize)) {
  128. if (!WideCharToMultiByte (CP_ACP,
  129. 0,
  130. pszServerName,
  131. -1,
  132. pszAnsiServerName,
  133. uSize,
  134. NULL,
  135. NULL))
  136. goto CleanUp;
  137. }
  138. else
  139. goto CleanUp;
  140. }
  141. arg = pszAnsiServerName;
  142. #else
  143. arg = pszServerName;
  144. #endif
  145. if (WSAStartup( 0x0101, &WsaData))
  146. goto CleanUp;
  147. // Added check for INADDR_NONE, MohsinA, 21-Oct-96.
  148. address = get_pingee(arg, &hostname, &was_inaddr, dnsreq);
  149. if(!address || (address == INADDR_NONE) ){
  150. SetLastError (DNS_ERROR_INVALID_IP_ADDRESS);
  151. goto CleanUp;
  152. }
  153. IcmpHandle = IcmpCreateFile();
  154. if (IcmpHandle == INVALID_HANDLE_VALUE) {
  155. goto CleanUp;
  156. }
  157. if (! (SendBuffer = (char *) LocalAlloc(LMEM_FIXED, SendSize))) {
  158. goto CleanUp;
  159. }
  160. //
  161. // Calculate receive buffer size and try to allocate it.
  162. //
  163. if (SendSize <= DEFAULT_SEND_SIZE) {
  164. RcvSize = DEFAULT_BUFFER_SIZE;
  165. }
  166. else {
  167. RcvSize = MAX_BUFFER_SIZE;
  168. }
  169. if (! (RcvBuffer = (char *)LocalAlloc(LMEM_FIXED, RcvSize))) {
  170. goto CleanUp;
  171. }
  172. //
  173. // Initialize the send buffer pattern.
  174. //
  175. for (i = 0; i < SendSize; i++) {
  176. SendBuffer[i] = 'a' + (i % 23);
  177. }
  178. //
  179. // Initialize the send options
  180. //
  181. SendOpts.OptionsData = Opt;
  182. SendOpts.OptionsSize = (UCHAR)OptLength;
  183. SendOpts.Ttl = TTL;
  184. SendOpts.Tos = TOS;
  185. SendOpts.Flags = Flags;
  186. addr.s_addr = address;
  187. #if 0
  188. if (hostname) {
  189. NlsPutMsg(
  190. STDOUT,
  191. PING_HEADER1,
  192. hostname,
  193. inet_ntoa(addr),
  194. SendSize
  195. );
  196. // printf("Pinging Host %s [%s]\n", hostname, inet_ntoa(addr));
  197. } else {
  198. NlsPutMsg(
  199. STDOUT,
  200. PING_HEADER2,
  201. inet_ntoa(addr),
  202. SendSize
  203. );
  204. // printf("Pinging Host [%s]\n", inet_ntoa(addr));
  205. }
  206. #endif
  207. // for (i = 0; i < Count; i++) {
  208. numberOfReplies = IcmpSendEcho(
  209. IcmpHandle,
  210. address,
  211. SendBuffer,
  212. (unsigned short) SendSize,
  213. &SendOpts,
  214. RcvBuffer,
  215. RcvSize,
  216. Timeout
  217. );
  218. if (numberOfReplies == 0) {
  219. errorCode = GetLastError();
  220. goto CleanUp;
  221. // Need to try again? - weihaic
  222. }
  223. else {
  224. reply = (PICMP_ECHO_REPLY) RcvBuffer;
  225. while (numberOfReplies--) {
  226. struct in_addr addr;
  227. addr.S_un.S_addr = reply->Address;
  228. // printf(
  229. // "Reply from %s:",
  230. // inet_ntoa(addr),
  231. // );
  232. if (reply->Status == IP_SUCCESS) {
  233. // printf(
  234. // "Echo size=%d ",
  235. // reply->DataSize
  236. // );
  237. bRet = TRUE;
  238. break;
  239. // printf("\n time rt=%dms min %d, max %d, total %d\n",
  240. // reply->RoundTripTime,
  241. // time_min, time_max, time_total );
  242. // printf("TTL=%u\n", (UINT)reply->Options.Ttl);
  243. //
  244. // Ignore Option fields
  245. // if (reply->Options.OptionsSize) {
  246. // ProcessOptions(reply, (BOOLEAN) dnsreq);
  247. //}
  248. }
  249. /* else {
  250. for (j=0; ErrorTable[j].Error != IP_GENERAL_FAILURE; j++) {
  251. if (ErrorTable[j].Error == reply->Status) {
  252. break;
  253. }
  254. }
  255. } */
  256. reply++;
  257. }
  258. }
  259. // }
  260. CleanUp:
  261. #ifdef UNICODE
  262. if (pszAnsiServerName) {
  263. LocalFree(pszAnsiServerName);
  264. }
  265. #endif
  266. if (IcmpHandle) {
  267. IcmpCloseHandle(IcmpHandle);
  268. }
  269. if (SendBuffer) {
  270. LocalFree(SendBuffer);
  271. }
  272. if (RcvBuffer) {
  273. LocalFree(RcvBuffer);
  274. }
  275. return bRet;
  276. }