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.

1084 lines
33 KiB

  1. /*++
  2. Copyright (c) 1991-2000 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. MohsinA, 21-Oct-96. INADDR_NONE check to avoid broadcast.
  13. MohsinA, 13-Nov-96. Max packet size < 64K.
  14. Notes:
  15. --*/
  16. //:ts=4
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <ctype.h>
  20. #include <time.h>
  21. #include <nt.h>
  22. #include <ntrtl.h>
  23. #include <nturtl.h>
  24. #include <snmp.h>
  25. #include <winsock2.h>
  26. #include "llinfo.h"
  27. #include "tcpcmd.h"
  28. #include "ipexport.h"
  29. #include "icmpapi.h"
  30. #include "nlstxt.h"
  31. #define MAX_BUFFER_SIZE (sizeof(ICMP_ECHO_REPLY) + 0xfff7 + MAX_OPT_SIZE)
  32. #define DEFAULT_BUFFER_SIZE (0x2000 - 8)
  33. #define DEFAULT_SEND_SIZE 32
  34. #define DEFAULT_COUNT 4
  35. #define DEFAULT_TTL 128
  36. #define DEFAULT_TOS 0
  37. #define DEFAULT_TIMEOUT 4000L
  38. #define MIN_INTERVAL 1000L
  39. #define STDOUT 1
  40. uchar SendOptions[MAX_OPT_SIZE];
  41. WSADATA WsaData;
  42. struct IPErrorTable {
  43. IP_STATUS Error; // The IP Error
  44. DWORD ErrorNlsID; // NLS string ID
  45. } ErrorTable[] =
  46. {
  47. { IP_BUF_TOO_SMALL, PING_BUF_TOO_SMALL},
  48. { IP_DEST_NET_UNREACHABLE, PING_DEST_NET_UNREACHABLE},
  49. { IP_DEST_HOST_UNREACHABLE, PING_DEST_HOST_UNREACHABLE},
  50. { IP_DEST_PROT_UNREACHABLE, PING_DEST_PROT_UNREACHABLE},
  51. { IP_DEST_PORT_UNREACHABLE, PING_DEST_PORT_UNREACHABLE},
  52. { IP_NO_RESOURCES, PING_NO_RESOURCES},
  53. { IP_BAD_OPTION, PING_BAD_OPTION},
  54. { IP_HW_ERROR, PING_HW_ERROR},
  55. { IP_PACKET_TOO_BIG, PING_PACKET_TOO_BIG},
  56. { IP_REQ_TIMED_OUT, PING_REQ_TIMED_OUT},
  57. { IP_BAD_REQ, PING_BAD_REQ},
  58. { IP_BAD_ROUTE, PING_BAD_ROUTE},
  59. { IP_TTL_EXPIRED_TRANSIT, PING_TTL_EXPIRED_TRANSIT},
  60. { IP_TTL_EXPIRED_REASSEM, PING_TTL_EXPIRED_REASSEM},
  61. { IP_PARAM_PROBLEM, PING_PARAM_PROBLEM},
  62. { IP_SOURCE_QUENCH, PING_SOURCE_QUENCH},
  63. { IP_OPTION_TOO_BIG, PING_OPTION_TOO_BIG},
  64. { IP_BAD_DESTINATION, PING_BAD_DESTINATION},
  65. { IP_NEGOTIATING_IPSEC, PING_NEGOTIATING_IPSEC},
  66. { IP_GENERAL_FAILURE, PING_GENERAL_FAILURE}
  67. };
  68. unsigned
  69. NlsPutMsg(unsigned Handle, unsigned usMsgNum, ...)
  70. {
  71. unsigned msglen;
  72. VOID * vp;
  73. va_list arglist;
  74. DWORD StrLen;
  75. va_start(arglist, usMsgNum);
  76. if (!(msglen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
  77. FORMAT_MESSAGE_FROM_HMODULE,
  78. NULL,
  79. usMsgNum,
  80. 0L, // Default country ID.
  81. (LPTSTR)&vp,
  82. 0,
  83. &arglist)))
  84. return(0);
  85. // Convert vp to oem
  86. StrLen=strlen(vp);
  87. CharToOemBuff((LPCTSTR)vp,(LPSTR)vp,StrLen);
  88. msglen = _write(Handle, vp, StrLen);
  89. LocalFree(vp);
  90. return(msglen);
  91. }
  92. void
  93. PrintUsage(void)
  94. {
  95. NlsPutMsg( STDOUT, PING_USAGE );
  96. // printf(
  97. // "Usage: ping [-s size] [-c count] [-d] [-l TTL] [-o options] [-t TOS]\n"
  98. // " [-w timeout] address.\n"
  99. // "Options:\n"
  100. // " -t Ping the specifed host until interrupted.\n"
  101. // " -l size Send buffer size.\n"
  102. // " -n count Send count.\n"
  103. // " -f Don't fragment.\n"
  104. // " -i TTL Time to live.\n"
  105. // " -v TOS Type of service\n"
  106. // " -w timeout Timeout (in milliseconds)\n"
  107. // " -r routes Record route.\n"
  108. // " -s routes Timestamp route.\n"
  109. // " -j ipaddress Loose source route.\n"
  110. // " -k ipaddress Strict source route.\n"
  111. // " -o IP options:\n"
  112. // " -ol hop list Loose source route.\n"
  113. // " -ot Timestamp.\n"
  114. // " -or Record route\n"
  115. // );
  116. }
  117. // ========================================================================
  118. // Caveat: return 0 for invalid, else internet address.
  119. // I would prefer -1 for error. - MohsinA, 21-Nov-96.
  120. unsigned long
  121. get_pingee(char *ahstr, char **hstr, int *was_inaddr, int dnsreq)
  122. {
  123. struct hostent *hostp = NULL;
  124. long inaddr;
  125. if ( strcmp( ahstr, "255.255.255.255" ) == 0 ) {
  126. return(0L);
  127. }
  128. if ((inaddr = inet_addr(ahstr)) == -1L) {
  129. hostp = gethostbyname(ahstr);
  130. if (hostp) {
  131. /*
  132. * If we find a host entry, set up the internet address
  133. */
  134. inaddr = *(long *)hostp->h_addr;
  135. *was_inaddr = 0;
  136. } else {
  137. // Neither dotted, not name.
  138. return(0L);
  139. }
  140. } else {
  141. // Is dotted.
  142. *was_inaddr = 1;
  143. if (dnsreq == 1) {
  144. hostp = gethostbyaddr((char *)&inaddr,sizeof(inaddr),AF_INET);
  145. }
  146. }
  147. *hstr = hostp ? hostp->h_name : (char *)NULL;
  148. return(inaddr);
  149. }
  150. unsigned long
  151. str2ip(char *addr, int *EndOffset)
  152. {
  153. char *endptr;
  154. char *start = addr;
  155. int i; // Counter variable.
  156. unsigned long curaddr = 0;
  157. unsigned long temp;
  158. struct hostent *hostp = NULL;
  159. for (i = 0; i < 4; i++) {
  160. temp = strtoul(addr, &endptr, 10);
  161. if (temp > 255)
  162. return 0L;
  163. if (endptr[0] != '.')
  164. if (i != 3)
  165. return 0L;
  166. else
  167. if (endptr[0] != '\0' && endptr[0] != ' ')
  168. return 0L;
  169. addr = endptr+1;
  170. curaddr = (curaddr << 8) + temp;
  171. }
  172. *EndOffset += (int)(endptr - start);
  173. return net_long(curaddr);
  174. }
  175. ulong
  176. param(char **argv, int argc, int current, ulong min, ulong max)
  177. {
  178. ulong temp;
  179. char *dummy;
  180. if (current == (argc - 1) ) {
  181. NlsPutMsg( STDOUT, PING_MESSAGE_1, argv[current] );
  182. // printf( "Value must be supplied for option %s.\n", argv[current]);
  183. exit(1);
  184. }
  185. temp = strtoul(argv[current+1], &dummy, 0);
  186. if (temp < min || temp > max) {
  187. NlsPutMsg( STDOUT, PING_MESSAGE_2, argv[current], min, max );
  188. // printf( "Bad value for option %s. range min..max\n",
  189. // argv[current], min, max );
  190. exit(1);
  191. }
  192. return temp;
  193. }
  194. void
  195. ProcessOptions(
  196. ICMP_ECHO_REPLY *reply,
  197. BOOLEAN DoReverseLookup)
  198. {
  199. UCHAR *optionPtr;
  200. UCHAR *endPtr;
  201. BOOLEAN done = FALSE;
  202. UCHAR optionLength;
  203. UCHAR entryEndPtr;
  204. UCHAR entryPtr;
  205. UCHAR addressMode;
  206. int entryCount = 0;
  207. optionPtr = reply->Options.OptionsData;
  208. endPtr = optionPtr + reply->Options.OptionsSize;
  209. while ((optionPtr < endPtr) && !done) {
  210. switch (*optionPtr) {
  211. case IP_OPT_EOL:
  212. done = TRUE;
  213. break;
  214. case IP_OPT_NOP:
  215. optionPtr++;
  216. break;
  217. case IP_OPT_SECURITY:
  218. optionPtr += 11;
  219. break;
  220. case IP_OPT_SID:
  221. optionPtr += 4;
  222. break;
  223. case IP_OPT_RR:
  224. case IP_OPT_LSRR:
  225. case IP_OPT_SSRR:
  226. if ((optionPtr + 3) > endPtr) {
  227. NlsPutMsg(STDOUT, PING_INVALID_RR_OPTION);
  228. done = TRUE;
  229. break;
  230. }
  231. optionLength = optionPtr[1];
  232. if (((optionPtr + optionLength) > endPtr) ||
  233. (optionLength < 3)
  234. ) {
  235. NlsPutMsg(STDOUT, PING_INVALID_RR_OPTION);
  236. done = TRUE;
  237. break;
  238. }
  239. entryEndPtr = optionPtr[2];
  240. if (entryEndPtr < 4) {
  241. NlsPutMsg(STDOUT, PING_INVALID_RR_OPTION);
  242. optionPtr += optionLength;
  243. break;
  244. }
  245. if (entryEndPtr > (optionLength + 1)) {
  246. entryEndPtr = optionLength + 1;
  247. }
  248. entryPtr = 4;
  249. entryCount = 0;
  250. NlsPutMsg(STDOUT, PING_ROUTE_HEADER1);
  251. while ((entryPtr + 3) < entryEndPtr) {
  252. struct in_addr routeAddress;
  253. if (entryCount) {
  254. NlsPutMsg(
  255. STDOUT,
  256. PING_ROUTE_SEPARATOR
  257. );
  258. if (entryCount == 1) {
  259. NlsPutMsg(STDOUT, PING_CR);
  260. NlsPutMsg(
  261. STDOUT,
  262. PING_ROUTE_HEADER2
  263. );
  264. entryCount = 0;
  265. }
  266. }
  267. entryCount++;
  268. routeAddress.S_un.S_addr =
  269. *( (IPAddr UNALIGNED *)
  270. (optionPtr + entryPtr - 1)
  271. );
  272. if (DoReverseLookup) {
  273. struct hostent *hostEntry;
  274. hostEntry = gethostbyaddr(
  275. (char *) &routeAddress,
  276. sizeof(routeAddress),
  277. AF_INET
  278. );
  279. if (hostEntry != NULL) {
  280. NlsPutMsg(
  281. STDOUT,
  282. PING_FULL_ROUTE_ENTRY,
  283. hostEntry->h_name,
  284. inet_ntoa(routeAddress)
  285. );
  286. } else {
  287. NlsPutMsg(
  288. STDOUT,
  289. PING_ROUTE_ENTRY,
  290. inet_ntoa(routeAddress)
  291. );
  292. }
  293. } else {
  294. NlsPutMsg(
  295. STDOUT,
  296. PING_ROUTE_ENTRY,
  297. inet_ntoa(routeAddress)
  298. );
  299. }
  300. entryPtr += 4;
  301. }
  302. NlsPutMsg(STDOUT, PING_CR);
  303. optionPtr += optionLength;
  304. break;
  305. case IP_OPT_TS:
  306. if ((optionPtr + 4) > endPtr) {
  307. NlsPutMsg(STDOUT, PING_INVALID_TS_OPTION);
  308. done = TRUE;
  309. break;
  310. }
  311. optionLength = optionPtr[1];
  312. entryEndPtr = optionPtr[2];
  313. if (entryEndPtr < 5) {
  314. NlsPutMsg(STDOUT, PING_INVALID_TS_OPTION);
  315. optionPtr += optionLength;
  316. break;
  317. }
  318. addressMode = optionPtr[3] & 1;
  319. if (entryEndPtr > (optionLength + 1)) {
  320. entryEndPtr = optionLength + 1;
  321. }
  322. entryPtr = 5;
  323. entryCount = 0;
  324. NlsPutMsg(STDOUT, PING_TS_HEADER1);
  325. while ((entryPtr + 3) < entryEndPtr) {
  326. struct in_addr routeAddress;
  327. ULONG timeStamp;
  328. if (entryCount) {
  329. NlsPutMsg(
  330. STDOUT,
  331. PING_ROUTE_SEPARATOR
  332. );
  333. if (entryCount == 1) {
  334. NlsPutMsg(STDOUT, PING_CR);
  335. NlsPutMsg(STDOUT, PING_TS_HEADER2);
  336. entryCount = 0;
  337. }
  338. }
  339. entryCount++;
  340. if (addressMode) {
  341. if ((entryPtr + 8) > entryEndPtr) {
  342. break;
  343. }
  344. routeAddress.S_un.S_addr =
  345. *( (IPAddr UNALIGNED *)
  346. (optionPtr + entryPtr - 1)
  347. );
  348. if (DoReverseLookup) {
  349. struct hostent *hostEntry;
  350. hostEntry = gethostbyaddr(
  351. (char *) &routeAddress,
  352. sizeof(routeAddress),
  353. AF_INET
  354. );
  355. if (hostEntry != NULL) {
  356. NlsPutMsg(
  357. STDOUT,
  358. PING_FULL_TS_ADDRESS,
  359. hostEntry->h_name,
  360. inet_ntoa(routeAddress)
  361. );
  362. } else {
  363. NlsPutMsg(
  364. STDOUT,
  365. PING_TS_ADDRESS,
  366. inet_ntoa(routeAddress)
  367. );
  368. }
  369. } else {
  370. NlsPutMsg(
  371. STDOUT,
  372. PING_TS_ADDRESS,
  373. inet_ntoa(routeAddress)
  374. );
  375. }
  376. entryPtr += 4;
  377. }
  378. timeStamp = *( (ULONG UNALIGNED *)
  379. (optionPtr + entryPtr - 1)
  380. );
  381. timeStamp = net_long(timeStamp);
  382. NlsPutMsg(
  383. STDOUT,
  384. PING_TS_TIMESTAMP,
  385. timeStamp
  386. );
  387. entryPtr += 4;
  388. }
  389. NlsPutMsg(STDOUT, PING_CR);
  390. optionPtr += optionLength;
  391. break;
  392. default:
  393. if ((optionPtr + 2) > endPtr) {
  394. done = TRUE;
  395. break;
  396. }
  397. optionPtr += optionPtr[1];
  398. break;
  399. }
  400. }
  401. }
  402. // ========================================================================
  403. // MohsinA, 05-Dec-96.
  404. IPAddr address=0; // was local to main earlier.
  405. uint num_send=0, num_recv=0,
  406. time_min=(uint)-1, time_max=0, time_total=0;
  407. void
  408. print_statistics( )
  409. {
  410. struct in_addr addr;
  411. if (num_send > 0) {
  412. addr.s_addr = address;
  413. if (time_min == (uint) -1) { // all times were off.
  414. time_min = 0;
  415. }
  416. // printf
  417. // "Ping statistics for %s:\n"
  418. // "Packets: Sent=%ul, received=%ul, lost=%d (%u%% loss),\n"
  419. // "Round trip times in milli-seconds: "
  420. // "minimum=%dms, maximum=%dms, average=%dms\n" ....
  421. NlsPutMsg(STDOUT, PING_STATISTICS,
  422. inet_ntoa(addr),
  423. num_send, num_recv, num_send - num_recv,
  424. (uint) ( 100 * (num_send - num_recv) / num_send ));
  425. if (num_recv > 0) {
  426. NlsPutMsg(STDOUT, PING_STATISTICS2,
  427. time_min, time_max, time_total / num_recv );
  428. }
  429. }
  430. }
  431. // ========================================================================
  432. // MohsinA, 05-Dec-96.
  433. // Press C-c to print and abort.
  434. // Press C-break to print and continue.
  435. BOOL
  436. ConsoleControlHandler(DWORD dwCtrlType)
  437. {
  438. print_statistics();
  439. switch ( dwCtrlType ) {
  440. case CTRL_BREAK_EVENT:
  441. NlsPutMsg( STDOUT, PING_BREAK );
  442. return TRUE;
  443. break;
  444. case CTRL_C_EVENT:
  445. NlsPutMsg( STDOUT, PING_INTERRUPT );
  446. default: break;
  447. }
  448. return FALSE;
  449. }
  450. uchar
  451. GetDefaultTTL(void)
  452. {
  453. HKEY registry=0;
  454. DWORD DefaultTTL=0;
  455. DWORD key_type;
  456. DWORD key_size = sizeof(DWORD);
  457. uchar TTL;
  458. DWORD Stat;
  459. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  460. "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
  461. 0,
  462. KEY_QUERY_VALUE,
  463. &registry) == ERROR_SUCCESS) {
  464. Stat=RegQueryValueEx(registry,
  465. "DefaultTTL",
  466. 0,
  467. &key_type,
  468. (unsigned char *)&DefaultTTL,
  469. &key_size);
  470. }
  471. if (DefaultTTL) {
  472. TTL = (unsigned char)DefaultTTL;
  473. } else {
  474. TTL = DEFAULT_TTL;
  475. }
  476. if (registry) {
  477. RegCloseKey(registry);
  478. }
  479. return TTL;
  480. }
  481. // ========================================================================
  482. void
  483. __cdecl
  484. main(int argc, char **argv)
  485. {
  486. char *arg;
  487. uint i;
  488. uint j;
  489. int found_addr = 0;
  490. int dnsreq = 0;
  491. char *hostname = NULL;
  492. int was_inaddr;
  493. DWORD numberOfReplies;
  494. uint Count = DEFAULT_COUNT;
  495. uchar TTL = 0;
  496. uchar *Opt = NULL; // Pointer to send options
  497. uint OptLength = 0;
  498. int OptIndex = 0; // Current index into SendOptions
  499. int SRIndex = -1; // Where to put address, if source routing
  500. uchar TOS = DEFAULT_TOS;
  501. uchar Flags = 0;
  502. ulong Timeout = DEFAULT_TIMEOUT;
  503. IP_OPTION_INFORMATION SendOpts;
  504. int EndOffset;
  505. ulong TempAddr;
  506. uchar TempCount;
  507. DWORD errorCode;
  508. HANDLE IcmpHandle;
  509. int err;
  510. struct in_addr addr;
  511. BOOL result;
  512. PICMP_ECHO_REPLY reply;
  513. BOOL sourceRouting = FALSE;
  514. char *SendBuffer, *RcvBuffer;
  515. uint RcvSize;
  516. uint SendSize = DEFAULT_SEND_SIZE;
  517. // ====================================================================
  518. err = WSAStartup( 0x0101, &WsaData);
  519. if (err) {
  520. NlsPutMsg(STDOUT, PING_WSASTARTUP_FAILED, GetLastError());
  521. exit(1);
  522. }
  523. TTL = GetDefaultTTL();
  524. if (argc < 2) {
  525. PrintUsage();
  526. exit(1);
  527. } else {
  528. i = 1;
  529. while (i < (uint) argc) {
  530. arg = argv[i];
  531. if ( (arg[0] == '-') || (arg[0] == '/') ) { // Have an option
  532. switch (arg[1]) {
  533. case '?':
  534. PrintUsage();
  535. exit(0);
  536. case 'l':
  537. // SendSize = (uint)param(argv, argc, i++, 0, 0xfff7);
  538. // A ping with packet size >= 64K can crash
  539. // some tcpip stacks during re-assembly,
  540. // So changed 'max' from 0xfff7 to 65500
  541. // - MohsinA, 13-Nov-96.
  542. SendSize = (uint)param(argv, argc, i++, 0, 65500 );
  543. break;
  544. case 't':
  545. Count = (uint)-1;
  546. break;
  547. case 'n':
  548. Count = (uint)param(argv, argc, i++, 1, 0xffffffff);
  549. break;
  550. case 'f':
  551. Flags = IP_FLAG_DF;
  552. break;
  553. case 'i':
  554. // TTL of zero is invalid, MohsinA, 13-Mar-97.
  555. TTL = (uchar)param(argv, argc, i++, 1, 0xff);
  556. break;
  557. case 'v':
  558. TOS = (uchar)param(argv, argc, i++, 0, 0xff);
  559. break;
  560. case 'w':
  561. Timeout = param(argv, argc, i++, 0, 0xffffffff);
  562. break;
  563. case 'a':
  564. dnsreq = 1;
  565. break;
  566. case 'r': // Record Route
  567. if ((OptIndex + 3) > MAX_OPT_SIZE) {
  568. NlsPutMsg(STDOUT, PING_TOO_MANY_OPTIONS);
  569. exit(1);
  570. }
  571. Opt = SendOptions;
  572. Opt[OptIndex] = IP_OPT_RR;
  573. Opt[OptIndex + 2] = 4; // Set initial pointer value
  574. // min is 1 not zero, MohsinA, 16-4-97.
  575. TempCount = (uchar)param(argv, argc, i++, 1, 9);
  576. TempCount = (TempCount * sizeof(ulong)) + 3;
  577. if ((TempCount + OptIndex) > MAX_OPT_SIZE) {
  578. NlsPutMsg(STDOUT, PING_TOO_MANY_OPTIONS);
  579. exit(1);
  580. }
  581. Opt[OptIndex+1] = TempCount;
  582. OptLength += TempCount;
  583. OptIndex += TempCount;
  584. break;
  585. case 's': // Timestamp
  586. if ((OptIndex + 4) > MAX_OPT_SIZE) {
  587. NlsPutMsg(STDOUT, PING_TOO_MANY_OPTIONS);
  588. exit(1);
  589. }
  590. Opt = SendOptions;
  591. Opt[OptIndex] = IP_OPT_TS;
  592. Opt[OptIndex + 2] = 5; // Set initial pointer value
  593. TempCount = (uchar)param(argv, argc, i++, 1, 4);
  594. TempCount = (TempCount * (sizeof(ulong) * 2)) + 4;
  595. if ((TempCount + OptIndex) > MAX_OPT_SIZE) {
  596. NlsPutMsg(STDOUT, PING_TOO_MANY_OPTIONS);
  597. exit(1);
  598. }
  599. Opt[OptIndex+1] = TempCount;
  600. Opt[OptIndex+3] = 1;
  601. OptLength += TempCount;
  602. OptIndex += TempCount;
  603. break;
  604. case 'j': // Loose source routing
  605. if (sourceRouting) {
  606. NlsPutMsg(STDOUT, PING_BAD_OPTION_COMBO);
  607. exit(1);
  608. }
  609. if ((OptIndex + 3) > MAX_OPT_SIZE) {
  610. NlsPutMsg(STDOUT, PING_TOO_MANY_OPTIONS);
  611. exit(1);
  612. }
  613. Opt = SendOptions;
  614. Opt[OptIndex] = IP_OPT_LSRR;
  615. Opt[OptIndex+1] = 3;
  616. Opt[OptIndex + 2] = 4; // Set initial pointer value
  617. OptLength += 3;
  618. while ( (i < (uint)(argc - 2)) && (*argv[i+1] != '-')) {
  619. if ((OptIndex + 3) > (MAX_OPT_SIZE - 4)) {
  620. NlsPutMsg(STDOUT, PING_TOO_MANY_OPTIONS);
  621. exit(1);
  622. }
  623. arg = argv[++i];
  624. EndOffset = 0;
  625. do {
  626. TempAddr = str2ip(arg + EndOffset, &EndOffset);
  627. if (!TempAddr) {
  628. NlsPutMsg( STDOUT, PING_MESSAGE_4 );
  629. // printf("Bad route specified for loose source route");
  630. exit(1);
  631. }
  632. j = Opt[OptIndex+1];
  633. *(ulong UNALIGNED *)&Opt[j+OptIndex] = TempAddr;
  634. Opt[OptIndex+1] += 4;
  635. OptLength += 4;
  636. while (arg[EndOffset] != '\0' && isspace(arg[EndOffset]))
  637. EndOffset++;
  638. } while (arg[EndOffset] != '\0');
  639. }
  640. SRIndex = Opt[OptIndex+1] + OptIndex;
  641. Opt[OptIndex+1] += 4; // Save space for dest. addr
  642. OptIndex += Opt[OptIndex+1];
  643. OptLength += 4;
  644. sourceRouting = TRUE;
  645. break;
  646. case 'k': // Strict source routing
  647. if (sourceRouting) {
  648. NlsPutMsg(STDOUT, PING_BAD_OPTION_COMBO);
  649. exit(1);
  650. }
  651. if ((OptIndex + 3) > MAX_OPT_SIZE) {
  652. NlsPutMsg(STDOUT, PING_TOO_MANY_OPTIONS);
  653. exit(1);
  654. }
  655. Opt = SendOptions;
  656. Opt[OptIndex] = IP_OPT_SSRR;
  657. Opt[OptIndex+1] = 3;
  658. Opt[OptIndex + 2] = 4; // Set initial pointer value
  659. OptLength += 3;
  660. while ( (i < (uint)(argc - 2)) && (*argv[i+1] != '-')) {
  661. if ((OptIndex + 3) > (MAX_OPT_SIZE - 4)) {
  662. NlsPutMsg(STDOUT, PING_TOO_MANY_OPTIONS);
  663. exit(1);
  664. }
  665. arg = argv[++i];
  666. EndOffset = 0;
  667. do {
  668. TempAddr = str2ip(arg + EndOffset, &EndOffset);
  669. if (!TempAddr) {
  670. NlsPutMsg( STDOUT, PING_MESSAGE_4 );
  671. // printf("Bad route specified for loose source route");
  672. exit(1);
  673. }
  674. j = Opt[OptIndex+1];
  675. *(ulong UNALIGNED *)&Opt[j+OptIndex] = TempAddr;
  676. Opt[OptIndex+1] += 4;
  677. OptLength += 4;
  678. while (arg[EndOffset] != '\0' && isspace(arg[EndOffset]))
  679. EndOffset++;
  680. } while (arg[EndOffset] != '\0');
  681. }
  682. SRIndex = Opt[OptIndex+1] + OptIndex;
  683. Opt[OptIndex+1] += 4; // Save space for dest. addr
  684. OptIndex += Opt[OptIndex+1];
  685. OptLength += 4;
  686. sourceRouting = TRUE;
  687. break;
  688. default:
  689. NlsPutMsg( STDOUT, PING_MESSAGE_11, arg );
  690. // printf( "Bad option %s.\n\n", arg);
  691. PrintUsage();
  692. exit(1);
  693. break;
  694. }
  695. i++;
  696. } else { // Not an option, must be an IP address.
  697. if (found_addr) {
  698. NlsPutMsg( STDOUT, PING_MESSAGE_12, arg );
  699. // printf( "Bad parameter %s.\n", arg);
  700. exit(1);
  701. }
  702. // Added check for INADDR_NONE, MohsinA, 21-Oct-96.
  703. address = get_pingee(arg, &hostname, &was_inaddr, dnsreq);
  704. if ( address && (address != INADDR_NONE) ) {
  705. found_addr = 1;
  706. i++;
  707. } else {
  708. NlsPutMsg( STDOUT, PING_MESSAGE_13, arg );
  709. // printf( "Bad IP address %s.\n", arg);
  710. // "Unknown host %s.", was Bug 1368.
  711. exit(1);
  712. }
  713. }
  714. }
  715. }
  716. if (!found_addr) {
  717. NlsPutMsg( STDOUT, PING_MESSAGE_14 );
  718. // printf("IP address must be specified.\n");
  719. exit(1);
  720. }
  721. if (SRIndex != -1) {
  722. *(ulong UNALIGNED *)&SendOptions[SRIndex] = address;
  723. }
  724. IcmpHandle = IcmpCreateFile();
  725. if (IcmpHandle == INVALID_HANDLE_VALUE) {
  726. NlsPutMsg( STDOUT, PING_MESSAGE_15, GetLastError() );
  727. // printf( "Unable to contact IP driver, error code %d.\n",
  728. // GetLastError() );
  729. exit(1);
  730. }
  731. SendBuffer = LocalAlloc(LMEM_FIXED, SendSize);
  732. if (SendBuffer == NULL) {
  733. NlsPutMsg(STDOUT, PING_NO_MEMORY);
  734. exit(1);
  735. }
  736. //
  737. // Calculate receive buffer size and try to allocate it.
  738. //
  739. if (SendSize <= DEFAULT_SEND_SIZE) {
  740. RcvSize = DEFAULT_BUFFER_SIZE;
  741. } else {
  742. RcvSize = MAX_BUFFER_SIZE;
  743. }
  744. RcvBuffer = LocalAlloc(LMEM_FIXED, RcvSize);
  745. if (RcvBuffer == NULL) {
  746. NlsPutMsg(STDOUT, PING_NO_MEMORY);
  747. LocalFree(SendBuffer);
  748. exit(1);
  749. }
  750. //
  751. // Initialize the send buffer pattern.
  752. //
  753. for (i = 0; i < SendSize; i++) {
  754. SendBuffer[i] = 'a' + (i % 23);
  755. }
  756. //
  757. // Initialize the send options
  758. //
  759. SendOpts.OptionsData = Opt;
  760. SendOpts.OptionsSize = (uchar)OptLength;
  761. SendOpts.Ttl = TTL;
  762. SendOpts.Tos = TOS;
  763. SendOpts.Flags = Flags;
  764. addr.s_addr = address;
  765. if (hostname) {
  766. NlsPutMsg(
  767. STDOUT,
  768. PING_HEADER1,
  769. hostname,
  770. inet_ntoa(addr),
  771. SendSize
  772. );
  773. // printf("Pinging Host %s [%s]\n", hostname, inet_ntoa(addr));
  774. } else {
  775. NlsPutMsg(
  776. STDOUT,
  777. PING_HEADER2,
  778. inet_ntoa(addr),
  779. SendSize
  780. );
  781. // printf("Pinging Host [%s]\n", inet_ntoa(addr));
  782. }
  783. SetConsoleCtrlHandler( &ConsoleControlHandler, TRUE );
  784. for (i = 0; i < Count; i++) {
  785. numberOfReplies = IcmpSendEcho2(IcmpHandle,
  786. 0,
  787. NULL,
  788. NULL,
  789. address,
  790. SendBuffer,
  791. (unsigned short) SendSize,
  792. &SendOpts,
  793. RcvBuffer,
  794. RcvSize,
  795. Timeout);
  796. num_send++;
  797. if (numberOfReplies == 0) {
  798. errorCode = GetLastError();
  799. if (errorCode < IP_STATUS_BASE) {
  800. NlsPutMsg( STDOUT, PING_MESSAGE_18, errorCode );
  801. // printf("PING: transmit failed, error code %lu\n", errorCode);
  802. } else {
  803. for (j = 0; ErrorTable[j].Error != errorCode &&
  804. ErrorTable[j].Error != IP_GENERAL_FAILURE;j++)
  805. ;
  806. NlsPutMsg( STDOUT, ErrorTable[j].ErrorNlsID );
  807. // printf("PING: %s.\n", ErrorTable[j].ErrorString);
  808. }
  809. if (i < (Count - 1)) {
  810. Sleep(MIN_INTERVAL);
  811. }
  812. } else {
  813. reply = (PICMP_ECHO_REPLY) RcvBuffer;
  814. while (numberOfReplies--) {
  815. struct in_addr addr;
  816. addr.S_un.S_addr = reply->Address;
  817. NlsPutMsg(STDOUT, PING_MESSAGE_19, inet_ntoa(addr));
  818. // printf(
  819. // "Reply from %s:",
  820. // inet_ntoa(addr),
  821. // );
  822. if (reply->Status == IP_SUCCESS) {
  823. NlsPutMsg( STDOUT, PING_MESSAGE_25, (int) reply->DataSize);
  824. // printf(
  825. // "Echo size=%d ",
  826. // reply->DataSize
  827. // );
  828. if (reply->DataSize != SendSize) {
  829. NlsPutMsg( STDOUT, PING_MESSAGE_20, SendSize );
  830. // printf("(sent %d) ", SendSize);
  831. } else {
  832. char *sendptr, *recvptr;
  833. sendptr = &(SendBuffer[0]);
  834. recvptr = (char *) reply->Data;
  835. for (j = 0; j < SendSize; j++)
  836. if (*sendptr++ != *recvptr++) {
  837. NlsPutMsg( STDOUT, PING_MESSAGE_21, j );
  838. // printf("- MISCOMPARE at offset %d - ", j);
  839. break;
  840. }
  841. }
  842. if (reply->RoundTripTime) {
  843. NlsPutMsg( STDOUT, PING_MESSAGE_22, reply->RoundTripTime );
  844. // Collect stats.
  845. time_total += reply->RoundTripTime;
  846. if ( reply->RoundTripTime < time_min ) {
  847. time_min = reply->RoundTripTime;
  848. }
  849. if ( reply->RoundTripTime > time_max ) {
  850. time_max = reply->RoundTripTime;
  851. }
  852. }
  853. else {
  854. NlsPutMsg( STDOUT, PING_MESSAGE_23 );
  855. // printf("time<1ms ");
  856. time_min = 0;
  857. }
  858. // printf("\n time rt=%dms min %d, max %d, total %d\n",
  859. // reply->RoundTripTime,
  860. // time_min, time_max, time_total );
  861. NlsPutMsg( STDOUT, PING_MESSAGE_24, (uint)reply->Options.Ttl );
  862. // printf("TTL=%u\n", (uint)reply->Options.Ttl);
  863. if (reply->Options.OptionsSize) {
  864. ProcessOptions(reply, (BOOLEAN) dnsreq);
  865. }
  866. } else {
  867. for (j=0; ErrorTable[j].Error != IP_GENERAL_FAILURE; j++) {
  868. if (ErrorTable[j].Error == reply->Status) {
  869. break;
  870. }
  871. }
  872. NlsPutMsg( STDOUT, ErrorTable[j].ErrorNlsID);
  873. }
  874. num_recv++;
  875. reply++;
  876. }
  877. if (i < (Count - 1)) {
  878. reply--;
  879. if (reply->RoundTripTime < MIN_INTERVAL) {
  880. Sleep(MIN_INTERVAL - reply->RoundTripTime);
  881. }
  882. }
  883. }
  884. }
  885. // MohsinA, 05-Dec-96. DCR # 65503.
  886. print_statistics();
  887. result = IcmpCloseHandle(IcmpHandle);
  888. LocalFree(SendBuffer);
  889. LocalFree(RcvBuffer);
  890. exit(0 == num_recv);
  891. }