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.

500 lines
15 KiB

  1. #include "diagnostics.h"
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <winsock2.h>
  5. #include <Ipexport.h>
  6. #include <icmpapi.h>
  7. #include <ctype.h>
  8. #define DEFAULT_SEND_SIZE 32
  9. #define DEFAULT_TTL 128
  10. #define DEFAULT_TOS 0
  11. #define DEFAULT_COUNT 4
  12. #define DEFAULT_TIMEOUT 4000L
  13. #define DEFAULT_BUFFER_SIZE (0x2000 - 8)
  14. #define MIN_INTERVAL 1000L
  15. struct IPErrorTable {
  16. IP_STATUS Error; // The IP Error
  17. DWORD ErrorNlsID; // NLS string ID
  18. } ErrorTable[] =
  19. {
  20. { IP_BUF_TOO_SMALL, PING_BUF_TOO_SMALL},
  21. { IP_DEST_NET_UNREACHABLE, PING_DEST_NET_UNREACHABLE},
  22. { IP_DEST_HOST_UNREACHABLE, PING_DEST_HOST_UNREACHABLE},
  23. { IP_DEST_PROT_UNREACHABLE, PING_DEST_PROT_UNREACHABLE},
  24. { IP_DEST_PORT_UNREACHABLE, PING_DEST_PORT_UNREACHABLE},
  25. { IP_NO_RESOURCES, PING_NO_RESOURCES},
  26. { IP_BAD_OPTION, PING_BAD_OPTION},
  27. { IP_HW_ERROR, PING_HW_ERROR},
  28. { IP_PACKET_TOO_BIG, PING_PACKET_TOO_BIG},
  29. { IP_REQ_TIMED_OUT, PING_REQ_TIMED_OUT},
  30. { IP_BAD_REQ, PING_BAD_REQ},
  31. { IP_BAD_ROUTE, PING_BAD_ROUTE},
  32. { IP_TTL_EXPIRED_TRANSIT, PING_TTL_EXPIRED_TRANSIT},
  33. { IP_TTL_EXPIRED_REASSEM, PING_TTL_EXPIRED_REASSEM},
  34. { IP_PARAM_PROBLEM, PING_PARAM_PROBLEM},
  35. { IP_SOURCE_QUENCH, PING_SOURCE_QUENCH},
  36. { IP_OPTION_TOO_BIG, PING_OPTION_TOO_BIG},
  37. { IP_BAD_DESTINATION, PING_BAD_DESTINATION},
  38. { IP_NEGOTIATING_IPSEC, PING_NEGOTIATING_IPSEC},
  39. { IP_GENERAL_FAILURE, PING_GENERAL_FAILURE}
  40. };
  41. UINT num_send=0, num_recv=0, time_min=(UINT)-1, time_max=0, time_total=0;
  42. IPAddr address=0;
  43. LPWSTR NlsPutMsg(HMODULE Handle, unsigned usMsgNum, ...);
  44. unsigned long get_pingee(char *ahstr, char **hstr, int *was_inaddr, int dnsreq);
  45. //void print_statistics();
  46. int CDiagnostics::Ping2(WCHAR *warg)
  47. {
  48. HANDLE IcmpHandle;
  49. IP_OPTION_INFORMATION SendOpts;
  50. UCHAR *Opt = NULL; // Pointer to send options
  51. UCHAR Flags = 0;
  52. char SendBuffer[DEFAULT_SEND_SIZE];
  53. char RcvBuffer[DEFAULT_BUFFER_SIZE];
  54. UINT SendSize = DEFAULT_SEND_SIZE;
  55. UINT RcvSize = DEFAULT_BUFFER_SIZE;
  56. UINT i;
  57. UINT j;
  58. char *hostname = NULL;
  59. int was_inaddr;
  60. int dnsreq = 0;
  61. struct in_addr addr;
  62. DWORD numberOfReplies;
  63. UINT Count = DEFAULT_COUNT;
  64. DWORD errorCode;
  65. PICMP_ECHO_REPLY reply;
  66. LPWSTR wszMsg, wszMsg2, wszMsg3, wszMsg4, wszMsg5;
  67. int SuccessCount = 0;
  68. char *arg;
  69. num_send=0;
  70. num_recv=0,
  71. time_min=(UINT)-1;
  72. time_max=0;
  73. time_total=0;
  74. address=0;
  75. if( warg == NULL )
  76. {
  77. wszMsg = NlsPutMsg(g_hModule,PING_NO_MEMORY,GetLastError());
  78. FormatPing(wszMsg);
  79. LocalFree(wszMsg);
  80. return FALSE;
  81. }
  82. int len = lstrlen(warg);
  83. if( len == 0 )
  84. {
  85. wszMsg = NlsPutMsg(g_hModule, IDS_PINGMSG_2,warg);
  86. FormatPing(wszMsg);
  87. LocalFree(wszMsg);
  88. return FALSE;
  89. }
  90. // Add the '\0' char
  91. len++;
  92. arg = (CHAR *)HeapAlloc(GetProcessHeap(),0,len * sizeof(WCHAR));
  93. if( !arg )
  94. {
  95. wszMsg = NlsPutMsg(g_hModule,IDS_PINGMSG_1,GetLastError());
  96. FormatPing(wszMsg);
  97. LocalFree(wszMsg);
  98. return FALSE;
  99. }
  100. if( -1 == wcstombs(arg,warg,len) )
  101. {
  102. wszMsg = NlsPutMsg(g_hModule, IDS_PINGMSG_2,warg);
  103. FormatPing(wszMsg);
  104. LocalFree(wszMsg);
  105. HeapFree(GetProcessHeap(),0,arg);
  106. return FALSE;
  107. }
  108. FormatPing(NULL);
  109. address = get_pingee(arg, &hostname, &was_inaddr, dnsreq);
  110. if ( !address || (address == INADDR_NONE) ) {
  111. wszMsg = NlsPutMsg(g_hModule, IDS_PINGMSG_2,warg);
  112. FormatPing(wszMsg);
  113. LocalFree(wszMsg);
  114. return 0;
  115. /*
  116. printf("Ping request could not find host %s. Please check the name and try again.\n",arg);
  117. exit(1);
  118. */
  119. }
  120. IcmpHandle = IcmpCreateFile();
  121. if (IcmpHandle == INVALID_HANDLE_VALUE) {
  122. wszMsg = NlsPutMsg(g_hModule, IDS_PINGMSG_3,GetLastError());
  123. FormatPing(wszMsg);
  124. LocalFree(wszMsg);
  125. return 0;
  126. /*
  127. printf( "Unable to contact IP driver, error code %d.\n",
  128. GetLastError() );
  129. exit(1);
  130. */
  131. }
  132. //
  133. // Initialize the send buffer pattern.
  134. //
  135. for (i = 0; i < SendSize; i++) {
  136. SendBuffer[i] = 'a' + (i % 23);
  137. }
  138. //
  139. // Initialize the send options
  140. //
  141. SendOpts.OptionsData = NULL;
  142. SendOpts.OptionsSize = 0;
  143. SendOpts.Ttl = DEFAULT_TTL;
  144. SendOpts.Tos = DEFAULT_TOS;
  145. SendOpts.Flags = Flags;
  146. addr.s_addr = address;
  147. if (hostname) {
  148. wszMsg = NlsPutMsg(g_hModule, IDS_PINGMSG_4,hostname,inet_ntoa(addr),SendSize);
  149. FormatPing(wszMsg);
  150. LocalFree(wszMsg);
  151. /*
  152. printf("\nPinging %s [%s] with %d bytes of data:\n\n",hostname,inet_ntoa(addr),SendSize);
  153. */
  154. }
  155. else
  156. {
  157. wszMsg = NlsPutMsg(g_hModule, IDS_PINGMSG_5,inet_ntoa(addr),SendSize);
  158. FormatPing(wszMsg);
  159. LocalFree(wszMsg);
  160. /*
  161. printf("\nPinging %s with %d bytes of data:\n\n",inet_ntoa(addr), SendSize);
  162. */
  163. }
  164. for (i = 0; i < Count; i++) {
  165. if( ShouldTerminate() ) goto end;
  166. numberOfReplies = IcmpSendEcho2(IcmpHandle,
  167. 0,
  168. NULL,
  169. NULL,
  170. address,
  171. SendBuffer,
  172. (unsigned short) SendSize,
  173. &SendOpts,
  174. RcvBuffer,
  175. RcvSize,
  176. DEFAULT_TIMEOUT);
  177. num_send++;
  178. if (numberOfReplies == 0) {
  179. errorCode = GetLastError();
  180. if (errorCode < IP_STATUS_BASE) {
  181. wszMsg = NlsPutMsg(g_hModule, IDS_PINGMSG_6,errorCode);
  182. FormatPing(wszMsg);
  183. LocalFree(wszMsg);
  184. /*
  185. printf("PING: transmit failed, error code %d.\n",errorCode);
  186. */
  187. } else {
  188. for (j = 0; ErrorTable[j].Error != errorCode &&
  189. ErrorTable[j].Error != IP_GENERAL_FAILURE;j++)
  190. ;
  191. wszMsg = NlsPutMsg(g_hModule, ErrorTable[j].ErrorNlsID);
  192. FormatPing(wszMsg);
  193. LocalFree(wszMsg);
  194. /*
  195. printf("%s\n",ErrorTable[j].ErrorNlsID);
  196. */
  197. }
  198. if (i < (Count - 1)) {
  199. Sleep(MIN_INTERVAL);
  200. }
  201. } else {
  202. /*
  203. wszMsg = NlsPutMsg(g_hModule, ErrorTable[j].ErrorNlsID);
  204. FormatPing(wszMsg);
  205. LocalFree(wszMsg);
  206. */
  207. reply = (PICMP_ECHO_REPLY) RcvBuffer;
  208. while (numberOfReplies--) {
  209. struct in_addr addr;
  210. addr.S_un.S_addr = reply->Address;
  211. wszMsg = NlsPutMsg(g_hModule, IDS_PINGMSG_7, inet_ntoa(addr));
  212. /*
  213. printf("Reply from %s: ",inet_ntoa(addr));
  214. */
  215. if (reply->Status == IP_SUCCESS) {
  216. wszMsg2 = NlsPutMsg(g_hModule, IDS_PINGMSG_8, wszMsg, (int) reply->DataSize);
  217. /*
  218. printf("bytes=%d ",(int) reply->DataSize);
  219. */
  220. if (reply->DataSize != SendSize) {
  221. wszMsg3 = NlsPutMsg(g_hModule, IDS_PINGMSG_9, wszMsg2, (int) reply->DataSize);
  222. /*
  223. printf("(sent %d) ",SendSize);
  224. */
  225. } else {
  226. char *sendptr, *recvptr;
  227. sendptr = &(SendBuffer[0]);
  228. recvptr = (char *) reply->Data;
  229. wszMsg3 = NlsPutMsg(g_hModule, IDS_PINGMSG_14, wszMsg2);
  230. for (j = 0; j < SendSize; j++)
  231. if (*sendptr++ != *recvptr++) {
  232. wszMsg3 = NlsPutMsg(g_hModule, IDS_PINGMSG_10, wszMsg2,j);
  233. /*
  234. printf("- MISCOMPARE at offset %d - ",j);
  235. */
  236. break;
  237. }
  238. }
  239. if (reply->RoundTripTime) {
  240. wszMsg4 = NlsPutMsg(g_hModule, IDS_PINGMSG_11, wszMsg3,reply->RoundTripTime);
  241. /*
  242. printf("time=%dms ",reply->RoundTripTime);
  243. */
  244. // Collect stats.
  245. time_total += reply->RoundTripTime;
  246. if ( reply->RoundTripTime < time_min ) {
  247. time_min = reply->RoundTripTime;
  248. }
  249. if ( reply->RoundTripTime > time_max ) {
  250. time_max = reply->RoundTripTime;
  251. }
  252. }
  253. else {
  254. wszMsg4 = NlsPutMsg(g_hModule, IDS_PINGMSG_12,wszMsg3);
  255. /*
  256. printf("time<1ms ");
  257. */
  258. time_min = 0;
  259. }
  260. wszMsg5 = NlsPutMsg(g_hModule, IDS_PINGMSG_13, wszMsg4,reply->RoundTripTime);
  261. /*
  262. printf("TTL=%d\n",(UINT)reply->Options.Ttl);
  263. */
  264. if (reply->Options.OptionsSize) {
  265. // void, we have no options
  266. //ProcessOptions(reply, (BOOLEAN) dnsreq);
  267. }
  268. FormatPing(wszMsg5);
  269. if(wszMsg) LocalFree(wszMsg);
  270. if(wszMsg2) LocalFree(wszMsg2);
  271. if(wszMsg3) LocalFree(wszMsg3);
  272. if(wszMsg4) LocalFree(wszMsg4);
  273. if(wszMsg5) LocalFree(wszMsg5);
  274. SuccessCount++;
  275. } else {
  276. for (j=0; ErrorTable[j].Error != IP_GENERAL_FAILURE; j++) {
  277. if (ErrorTable[j].Error == reply->Status) {
  278. break;
  279. }
  280. }
  281. wszMsg = NlsPutMsg(g_hModule, ErrorTable[j].ErrorNlsID);
  282. FormatPing(wszMsg);
  283. LocalFree(wszMsg);
  284. /*
  285. printf("%s",ErrorTable[j].ErrorNlsID);
  286. */
  287. }
  288. num_recv++;
  289. reply++;
  290. }
  291. if (i < (Count - 1)) {
  292. reply--;
  293. if (reply->RoundTripTime < MIN_INTERVAL) {
  294. Sleep(MIN_INTERVAL - reply->RoundTripTime);
  295. }
  296. }
  297. }
  298. }
  299. print_statistics();
  300. end:
  301. (void)IcmpCloseHandle(IcmpHandle);
  302. HeapFree(GetProcessHeap(),0,arg);
  303. return SuccessCount == Count;
  304. }
  305. unsigned long
  306. get_pingee(char *ahstr, char **hstr, int *was_inaddr, int dnsreq)
  307. {
  308. struct hostent *hostp = NULL;
  309. long inaddr;
  310. if ( strcmp( ahstr, "255.255.255.255" ) == 0 ) {
  311. return(0L);
  312. }
  313. if ((inaddr = inet_addr(ahstr)) == -1L) {
  314. hostp = gethostbyname(ahstr);
  315. if (hostp) {
  316. /*
  317. * If we find a host entry, set up the internet address
  318. */
  319. inaddr = *(long *)hostp->h_addr;
  320. *was_inaddr = 0;
  321. } else {
  322. // Neither dotted, not name.
  323. return(0L);
  324. }
  325. } else {
  326. // Is dotted.
  327. *was_inaddr = 1;
  328. if (dnsreq == 1) {
  329. hostp = gethostbyaddr((char *)&inaddr,sizeof(inaddr),AF_INET);
  330. }
  331. }
  332. *hstr = hostp ? hostp->h_name : (char *)NULL;
  333. return(inaddr);
  334. }
  335. void
  336. CDiagnostics::print_statistics( )
  337. {
  338. struct in_addr addr;
  339. LPWSTR wszMsg;
  340. if (num_send > 0) {
  341. addr.s_addr = address;
  342. if (time_min == (UINT) -1) { // all times were off.
  343. time_min = 0;
  344. }
  345. wszMsg = NlsPutMsg(g_hModule, IDS_PINGMSG_15,inet_ntoa(addr));
  346. FormatPing(wszMsg);
  347. LocalFree(wszMsg);
  348. /*
  349. printf("\n");
  350. printf("Ping statistics for %s:\n",inet_ntoa(addr));
  351. */
  352. wszMsg = NlsPutMsg(g_hModule, IDS_PINGMSG_16,
  353. num_send, num_recv,num_send - num_recv,(UINT) ( 100 * (num_send - num_recv) / num_send ));
  354. FormatPing(wszMsg);
  355. LocalFree(wszMsg);
  356. /*
  357. printf(" Packets: Sent = %d, Received = %d, Lost = %d (%u%% loss)\n",
  358. num_send, num_recv,num_send - num_recv,(UINT) ( 100 * (num_send - num_recv) / num_send ));
  359. */
  360. if (num_recv > 0) {
  361. wszMsg = NlsPutMsg(g_hModule, IDS_PINGMSG_17);
  362. FormatPing(wszMsg);
  363. LocalFree(wszMsg);
  364. /*
  365. printf("Approximate round trip times in milli-seconds:\n");
  366. */
  367. wszMsg = NlsPutMsg(g_hModule, IDS_PINGMSG_18,
  368. time_min, time_max, time_total / num_recv);
  369. FormatPing(wszMsg);
  370. LocalFree(wszMsg);
  371. /*
  372. printf(" Minimum = %dms, Maximum = %dms, Average = %dms\n",time_min, time_max, time_total / num_recv);
  373. */
  374. }
  375. }
  376. }
  377. LPWSTR
  378. NlsPutMsg(HMODULE Handle, unsigned usMsgNum, ...)
  379. {
  380. unsigned msglen;
  381. VOID * vp = NULL;
  382. va_list arglist;
  383. DWORD StrLen;
  384. WCHAR wszFormat[5000]; //BUGBUG hardcode value
  385. int ret;
  386. if( (ret=LoadString(Handle,usMsgNum,wszFormat,5000))!=0 )
  387. {
  388. va_start(arglist, usMsgNum);
  389. if (!(msglen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
  390. FORMAT_MESSAGE_FROM_STRING,
  391. wszFormat,
  392. 0,
  393. 0L, // Default country ID.
  394. (LPTSTR)&vp,
  395. 0,
  396. &arglist)))
  397. {
  398. return NULL;
  399. }
  400. }
  401. return (LPWSTR)vp;
  402. /*
  403. // Convert vp to oem
  404. StrLen=strlen(vp);
  405. CharToOemBuff((LPCTSTR)vp,(LPSTR)vp,StrLen);
  406. msglen = _write(Handle, vp, StrLen);
  407. LocalFree(vp);
  408. return(msglen);
  409. */
  410. }