1 /* 2 * PROJECT: ReactOS netstat utility 3 * LICENSE: GPL - See COPYING in the top level directory 4 * PURPOSE: display IP stack statistics 5 * COPYRIGHT: Copyright 2005 Ged Murphy <gedmurphy@gmail.com> 6 */ 7 /* 8 * TODO: 9 * implement -b, -t, -v 10 * clean up GetIpHostName 11 */ 12 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <wchar.h> 16 17 #define WIN32_NO_STATUS 18 #include <windef.h> 19 #include <winbase.h> 20 #define _INC_WINDOWS 21 #include <winsock2.h> 22 #include <iphlpapi.h> 23 24 #include <conutils.h> 25 26 #include "netstat.h" 27 #include "resource.h" 28 29 enum ProtoType {IP, TCP, UDP, ICMP} Protocol; 30 DWORD Interval; /* time to pause between printing output */ 31 32 /* TCP endpoint states */ 33 PCWSTR TcpState[] = { 34 L"???", 35 L"CLOSED", 36 L"LISTENING", 37 L"SYN_SENT", 38 L"SYN_RCVD", 39 L"ESTABLISHED", 40 L"FIN_WAIT1", 41 L"FIN_WAIT2", 42 L"CLOSE_WAIT", 43 L"CLOSING", 44 L"LAST_ACK", 45 L"TIME_WAIT", 46 L"DELETE_TCB" 47 }; 48 49 /* 50 * format message string and display output 51 */ 52 VOID DoFormatMessage(DWORD ErrorCode) 53 { 54 if (ErrorCode == ERROR_SUCCESS) 55 return; 56 57 ConMsgPuts(StdErr, FORMAT_MESSAGE_FROM_SYSTEM, 58 NULL, ErrorCode, LANG_USER_DEFAULT); 59 } 60 61 VOID DisplayTableHeader(VOID) 62 { 63 ConResPuts(StdOut, IDS_ACTIVE_CONNECT); 64 ConResPuts(StdOut, IDS_DISPLAY_THEADER); 65 if (bDoShowProcessId) 66 ConResPuts(StdOut, IDS_DISPLAY_PROCESS); 67 else 68 ConPuts(StdOut, L"\n"); 69 } 70 71 /* 72 * Parse command line parameters and set any options 73 */ 74 BOOL ParseCmdline(int argc, wchar_t* argv[]) 75 { 76 LPWSTR Proto; 77 WCHAR c; 78 INT i; 79 80 if ((argc == 1) || (iswdigit(*argv[1]))) 81 bNoOptions = TRUE; 82 83 /* Parse command line for options we have been given. */ 84 for (i = 1; i < argc; i++) 85 { 86 if ((argc > 1) && (argv[i][0] == L'-' || argv[i][0] == L'/')) 87 { 88 while ((c = *++argv[i]) != L'\0') 89 { 90 switch (towlower(c)) 91 { 92 case L'a': 93 bDoShowAllCons = TRUE; 94 break; 95 case L'b': 96 // UNIMPLEMENTED. 97 ConPuts(StdErr, L"'b' option is FIXME (Accepted option though unimplemented feature).\n"); 98 bDoShowProcName = TRUE; 99 #if (_WIN32_WINNT < _WIN32_WINNT_VISTA) 100 bDoShowProcessId = TRUE; 101 #endif 102 break; 103 case L'e': 104 bDoShowEthStats = TRUE; 105 break; 106 case L'n': 107 bDoShowNumbers = TRUE; 108 break; 109 case L'o': 110 bDoShowProcessId = TRUE; 111 break; 112 case L'p': 113 bDoShowProtoCons = TRUE; 114 if (i+1 >= argc) 115 { 116 DisplayTableHeader(); 117 return TRUE; 118 } 119 120 Proto = argv[i+1]; 121 if (!_wcsicmp(L"IP", Proto)) 122 Protocol = IP; 123 else if (!_wcsicmp(L"ICMP", Proto)) 124 Protocol = ICMP; 125 else if (!_wcsicmp(L"TCP", Proto)) 126 Protocol = TCP; 127 else if (!_wcsicmp(L"UDP", Proto)) 128 Protocol = UDP; 129 else 130 goto StopParsingAndShowUsageHelp; 131 break; 132 case L'r': 133 bDoShowRouteTable = TRUE; 134 break; 135 case L's': 136 bDoShowProtoStats = TRUE; 137 break; 138 case L't': 139 // UNIMPLEMENTED. 140 ConPuts(StdErr, L"'t' option is FIXME (Accepted option though unimplemented feature).\n"); 141 break; 142 case L'v': 143 // UNIMPLEMENTED. 144 ConPuts(StdErr, L"'v' option is FIXME (Accepted option though unimplemented feature).\n"); 145 bDoDispSeqComp = TRUE; 146 break; 147 default: 148 StopParsingAndShowUsageHelp: 149 ConResPuts(StdErr, IDS_USAGE); 150 return FALSE; 151 } 152 } 153 } 154 else if (iswdigit(*argv[i]) != 0) 155 { 156 if (swscanf(argv[i], L"%lu", &Interval) != EOF) 157 bLoopOutput = TRUE; 158 else 159 return FALSE; 160 } 161 } 162 163 return TRUE; 164 } 165 166 BOOL DisplayOutput(VOID) 167 { 168 if (bNoOptions) 169 { 170 DisplayTableHeader(); 171 return ShowTcpTable(); 172 } 173 174 if (bDoShowRouteTable) 175 { 176 if (_wsystem(L"route print") == -1) 177 { 178 ConResPuts(StdErr, IDS_ERROR_ROUTE); 179 return FALSE; 180 } 181 return TRUE; 182 } 183 184 if (bDoShowEthStats) 185 { 186 ShowEthernetStatistics(); 187 return TRUE; 188 } 189 190 if (bDoShowProtoCons) 191 { 192 switch (Protocol) 193 { 194 case IP: 195 if (bDoShowProtoStats) 196 ShowIpStatistics(); 197 return TRUE; 198 case ICMP: 199 if (bDoShowProtoStats) 200 ShowIcmpStatistics(); 201 return TRUE; 202 case TCP: 203 if (bDoShowProtoStats) 204 ShowTcpStatistics(); 205 DisplayTableHeader(); 206 return ShowTcpTable(); 207 case UDP: 208 if (bDoShowProtoStats) 209 ShowUdpStatistics(); 210 DisplayTableHeader(); 211 return (bDoShowAllCons ? ShowUdpTable() : TRUE); 212 default: 213 break; 214 } 215 } 216 else if (bDoShowProtoStats) 217 { 218 ShowIpStatistics(); 219 ShowIcmpStatistics(); 220 ShowTcpStatistics(); 221 ShowUdpStatistics(); 222 return TRUE; 223 } 224 else 225 { 226 DisplayTableHeader(); 227 if (ShowTcpTable() && bDoShowAllCons) 228 ShowUdpTable(); 229 } 230 231 return TRUE; 232 } 233 234 VOID ShowIpStatistics(VOID) 235 { 236 MIB_IPSTATS IpStats; 237 DWORD dwRetVal; 238 239 if ((dwRetVal = GetIpStatistics(&IpStats)) == NO_ERROR) 240 { 241 ConResPuts(StdOut, IDS_IP4_STAT_HEADER); 242 ConResPrintf(StdOut, IDS_IP_PACK_REC, IpStats.dwInReceives); 243 ConResPrintf(StdOut, IDS_IP_HEAD_REC_ERROR, IpStats.dwInHdrErrors); 244 ConResPrintf(StdOut, IDS_IP_ADDR_REC_ERROR, IpStats.dwInAddrErrors); 245 ConResPrintf(StdOut, IDS_IP_DATAG_FWD, IpStats.dwForwDatagrams); 246 ConResPrintf(StdOut, IDS_IP_UNKNOWN_PRO_REC, IpStats.dwInUnknownProtos); 247 ConResPrintf(StdOut, IDS_IP_REC_PACK_DISCARD, IpStats.dwInDiscards); 248 ConResPrintf(StdOut, IDS_IP_REC_PACK_DELIVER, IpStats.dwInDelivers); 249 ConResPrintf(StdOut, IDS_IP_OUT_REQUEST, IpStats.dwOutRequests); 250 ConResPrintf(StdOut, IDS_IP_ROUTE_DISCARD, IpStats.dwRoutingDiscards); 251 ConResPrintf(StdOut, IDS_IP_DISCARD_OUT_PACK, IpStats.dwOutDiscards); 252 ConResPrintf(StdOut, IDS_IP_OUT_PACKET_NO_ROUTE, IpStats.dwOutNoRoutes); 253 ConResPrintf(StdOut, IDS_IP_REASSEMBLE_REQUIRED, IpStats.dwReasmReqds); 254 ConResPrintf(StdOut, IDS_IP_REASSEMBLE_SUCCESS, IpStats.dwReasmOks); 255 ConResPrintf(StdOut, IDS_IP_REASSEMBLE_FAILURE, IpStats.dwReasmFails); 256 ConResPrintf(StdOut, IDS_IP_DATAG_FRAG_SUCCESS, IpStats.dwFragOks); 257 ConResPrintf(StdOut, IDS_IP_DATAG_FRAG_FAILURE, IpStats.dwFragFails); 258 ConResPrintf(StdOut, IDS_IP_DATAG_FRAG_CREATE, IpStats.dwFragCreates); 259 } 260 else 261 { 262 DoFormatMessage(dwRetVal); 263 } 264 } 265 266 VOID ShowIcmpStatistics(VOID) 267 { 268 MIB_ICMP IcmpStats; 269 DWORD dwRetVal; 270 271 if ((dwRetVal = GetIcmpStatistics(&IcmpStats)) == NO_ERROR) 272 { 273 ConResPuts(StdOut, IDS_ICMP4_STAT_HEADER); 274 ConResPuts(StdOut, IDS_ICMP_THEADER); 275 ConResPrintf(StdOut, IDS_ICMP_MSG, 276 IcmpStats.stats.icmpInStats.dwMsgs, IcmpStats.stats.icmpOutStats.dwMsgs); 277 ConResPrintf(StdOut, IDS_ICMP_ERROR, 278 IcmpStats.stats.icmpInStats.dwErrors, IcmpStats.stats.icmpOutStats.dwErrors); 279 ConResPrintf(StdOut, IDS_ICMP_DEST_UNREACH, 280 IcmpStats.stats.icmpInStats.dwDestUnreachs, IcmpStats.stats.icmpOutStats.dwDestUnreachs); 281 ConResPrintf(StdOut, IDS_ICMP_TIME_EXCEED, 282 IcmpStats.stats.icmpInStats.dwTimeExcds, IcmpStats.stats.icmpOutStats.dwTimeExcds); 283 ConResPrintf(StdOut, IDS_ICMP_PARAM_PROBLEM, 284 IcmpStats.stats.icmpInStats.dwParmProbs, IcmpStats.stats.icmpOutStats.dwParmProbs); 285 ConResPrintf(StdOut, IDS_ICMP_SRC_QUENCHES, 286 IcmpStats.stats.icmpInStats.dwSrcQuenchs, IcmpStats.stats.icmpOutStats.dwSrcQuenchs); 287 ConResPrintf(StdOut, IDS_ICMP_REDIRECT, 288 IcmpStats.stats.icmpInStats.dwRedirects, IcmpStats.stats.icmpOutStats.dwRedirects); 289 ConResPrintf(StdOut, IDS_ICMP_ECHO, 290 IcmpStats.stats.icmpInStats.dwEchos, IcmpStats.stats.icmpOutStats.dwEchos); 291 ConResPrintf(StdOut, IDS_ICMP_ECHO_REPLY, 292 IcmpStats.stats.icmpInStats.dwEchoReps, IcmpStats.stats.icmpOutStats.dwEchoReps); 293 ConResPrintf(StdOut, IDS_ICMP_TIMESTAMP, 294 IcmpStats.stats.icmpInStats.dwTimestamps, IcmpStats.stats.icmpOutStats.dwTimestamps); 295 ConResPrintf(StdOut, IDS_ICMP_TIMESTAMP_REPLY, 296 IcmpStats.stats.icmpInStats.dwTimestampReps, IcmpStats.stats.icmpOutStats.dwTimestampReps); 297 ConResPrintf(StdOut, IDS_ICMP_ADDRESSS_MASK, 298 IcmpStats.stats.icmpInStats.dwAddrMasks, IcmpStats.stats.icmpOutStats.dwAddrMasks); 299 ConResPrintf(StdOut, IDS_ICMP_ADDRESSS_MASK_REPLY, 300 IcmpStats.stats.icmpInStats.dwAddrMaskReps, IcmpStats.stats.icmpOutStats.dwAddrMaskReps); 301 } 302 else 303 { 304 DoFormatMessage(dwRetVal); 305 } 306 } 307 308 VOID ShowTcpStatistics(VOID) 309 { 310 MIB_TCPSTATS tcpStats; 311 DWORD dwRetVal; 312 313 if ((dwRetVal = GetTcpStatistics(&tcpStats)) == NO_ERROR) 314 { 315 ConResPuts(StdOut, IDS_TCP4_HEADER); 316 ConResPrintf(StdOut, IDS_TCP_ACTIVE_OPEN, tcpStats.dwActiveOpens); 317 ConResPrintf(StdOut, IDS_TCP_PASS_OPEN, tcpStats.dwPassiveOpens); 318 ConResPrintf(StdOut, IDS_TCP_FAIL_CONNECT, tcpStats.dwAttemptFails); 319 ConResPrintf(StdOut, IDS_TCP_RESET_CONNECT, tcpStats.dwEstabResets); 320 ConResPrintf(StdOut, IDS_TCP_CURRENT_CONNECT, tcpStats.dwCurrEstab); 321 ConResPrintf(StdOut, IDS_TCP_SEG_RECEIVE, tcpStats.dwInSegs); 322 ConResPrintf(StdOut, IDS_TCP_SEG_SENT, tcpStats.dwOutSegs); 323 ConResPrintf(StdOut, IDS_TCP_SEG_RETRANSMIT, tcpStats.dwRetransSegs); 324 } 325 else 326 { 327 DoFormatMessage(dwRetVal); 328 } 329 } 330 331 VOID ShowUdpStatistics(VOID) 332 { 333 MIB_UDPSTATS udpStats; 334 DWORD dwRetVal; 335 336 if ((dwRetVal = GetUdpStatistics(&udpStats)) == NO_ERROR) 337 { 338 ConResPuts(StdOut, IDS_UDP_IP4_HEADER); 339 ConResPrintf(StdOut, IDS_UDP_DATAG_RECEIVE, udpStats.dwInDatagrams); 340 ConResPrintf(StdOut, IDS_UDP_NO_PORT, udpStats.dwNoPorts); 341 ConResPrintf(StdOut, IDS_UDP_RECEIVE_ERROR, udpStats.dwInErrors); 342 ConResPrintf(StdOut, IDS_UDP_DATAG_SEND, udpStats.dwOutDatagrams); 343 } 344 else 345 { 346 DoFormatMessage(dwRetVal); 347 } 348 } 349 350 VOID ShowEthernetStatistics(VOID) 351 { 352 PMIB_IFTABLE pIfTable; 353 DWORD dwSize = 0; 354 DWORD dwRetVal = 0; 355 356 pIfTable = (MIB_IFTABLE*)HeapAlloc(GetProcessHeap(), 0, sizeof(MIB_IFTABLE)); 357 358 if (GetIfTable(pIfTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) 359 { 360 HeapFree(GetProcessHeap(), 0, pIfTable); 361 pIfTable = (MIB_IFTABLE*)HeapAlloc(GetProcessHeap(), 0, dwSize); 362 363 if ((dwRetVal = GetIfTable(pIfTable, &dwSize, 0)) == NO_ERROR) 364 { 365 ConResPuts(StdOut, IDS_ETHERNET_INTERFACE_STAT); 366 ConResPuts(StdOut, IDS_ETHERNET_THEADER); 367 ConResPrintf(StdOut, IDS_ETHERNET_BYTES, 368 pIfTable->table[0].dwInOctets, pIfTable->table[0].dwOutOctets); 369 ConResPrintf(StdOut, IDS_ETHERNET_UNICAST_PACKET, 370 pIfTable->table[0].dwInUcastPkts, pIfTable->table[0].dwOutUcastPkts); 371 ConResPrintf(StdOut, IDS_ETHERNET_NON_UNICAST_PACKET, 372 pIfTable->table[0].dwInNUcastPkts, pIfTable->table[0].dwOutNUcastPkts); 373 ConResPrintf(StdOut, IDS_ETHERNET_DISCARD, 374 pIfTable->table[0].dwInDiscards, pIfTable->table[0].dwOutDiscards); 375 ConResPrintf(StdOut, IDS_ETHERNET_ERROR, 376 pIfTable->table[0].dwInErrors, pIfTable->table[0].dwOutErrors); 377 ConResPrintf(StdOut, IDS_ETHERNET_UNKNOWN, 378 pIfTable->table[0].dwInUnknownProtos); 379 } 380 else 381 { 382 DoFormatMessage(dwRetVal); 383 } 384 } 385 HeapFree(GetProcessHeap(), 0, pIfTable); 386 } 387 388 BOOL ShowTcpTable(VOID) 389 { 390 PMIB_TCPTABLE_OWNER_PID tcpTable; 391 DWORD error, dwSize; 392 DWORD i; 393 CHAR HostIp[HOSTNAMELEN], HostPort[PORTNAMELEN]; 394 CHAR RemoteIp[HOSTNAMELEN], RemotePort[PORTNAMELEN]; 395 CHAR Host[ADDRESSLEN]; 396 CHAR Remote[ADDRESSLEN]; 397 CHAR PID[64]; 398 399 /* Get the table of TCP endpoints */ 400 dwSize = sizeof(MIB_TCPTABLE_OWNER_PID); 401 /* Should also work when we get new connections between 2 GetTcpTable() 402 * calls: */ 403 do 404 { 405 tcpTable = (PMIB_TCPTABLE_OWNER_PID)HeapAlloc(GetProcessHeap(), 0, dwSize); 406 error = GetExtendedTcpTable(tcpTable, &dwSize, TRUE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0); 407 if (error != NO_ERROR) 408 HeapFree(GetProcessHeap(), 0, tcpTable); 409 } 410 while (error == ERROR_INSUFFICIENT_BUFFER); 411 412 if (error != NO_ERROR) 413 { 414 ConResPrintf(StdErr, IDS_ERROR_TCP_SNAPSHOT); 415 DoFormatMessage(error); 416 return FALSE; 417 } 418 419 /* Dump the TCP table */ 420 for (i = 0; i < tcpTable->dwNumEntries; i++) 421 { 422 /* If we aren't showing all connections, only display established, close wait 423 * and time wait. This is the default output for netstat */ 424 if (bDoShowAllCons || (tcpTable->table[i].dwState == MIB_TCP_STATE_ESTAB) 425 || (tcpTable->table[i].dwState == MIB_TCP_STATE_CLOSE_WAIT) 426 || (tcpTable->table[i].dwState == MIB_TCP_STATE_TIME_WAIT)) 427 { 428 /* I've split this up so it's easier to follow */ 429 GetIpHostName(TRUE, tcpTable->table[i].dwLocalAddr, HostIp, sizeof(HostIp)); 430 GetPortName(tcpTable->table[i].dwLocalPort, "tcp", HostPort, sizeof(HostPort)); 431 sprintf(Host, "%s:%s", HostIp, HostPort); 432 433 if (tcpTable->table[i].dwState == MIB_TCP_STATE_LISTEN) 434 { 435 sprintf(Remote, "%s:0", HostIp); 436 } 437 else 438 { 439 GetIpHostName(FALSE, tcpTable->table[i].dwRemoteAddr, RemoteIp, sizeof(RemoteIp)); 440 GetPortName(tcpTable->table[i].dwRemotePort, "tcp", RemotePort, sizeof(RemotePort)); 441 sprintf(Remote, "%s:%s", RemoteIp, RemotePort); 442 } 443 444 if (bDoShowProcessId) 445 { 446 sprintf(PID, "%ld", tcpTable->table[i].dwOwningPid); 447 } 448 else 449 { 450 PID[0] = 0; 451 } 452 453 ConPrintf(StdOut, L" %-6s %-22S %-22S %-11s %S\n", L"TCP", 454 Host, Remote, TcpState[tcpTable->table[i].dwState], PID); 455 } 456 } 457 458 HeapFree(GetProcessHeap(), 0, tcpTable); 459 return TRUE; 460 } 461 462 BOOL ShowUdpTable(VOID) 463 { 464 PMIB_UDPTABLE_OWNER_PID udpTable; 465 DWORD error, dwSize; 466 DWORD i; 467 CHAR HostIp[HOSTNAMELEN], HostPort[PORTNAMELEN]; 468 CHAR Host[ADDRESSLEN]; 469 CHAR PID[64]; 470 471 /* Get the table of UDP endpoints */ 472 dwSize = 0; 473 error = GetExtendedUdpTable(NULL, &dwSize, TRUE, AF_INET, UDP_TABLE_OWNER_PID, 0); 474 if (error != ERROR_INSUFFICIENT_BUFFER) 475 { 476 ConResPuts(StdErr, IDS_ERROR_UDP_ENDPOINT); 477 DoFormatMessage(error); 478 return FALSE; 479 } 480 udpTable = (PMIB_UDPTABLE_OWNER_PID)HeapAlloc(GetProcessHeap(), 0, dwSize); 481 error = GetExtendedUdpTable(udpTable, &dwSize, TRUE, AF_INET, UDP_TABLE_OWNER_PID, 0); 482 if (error) 483 { 484 ConResPuts(StdErr, IDS_ERROR_UDP_ENDPOINT_TABLE); 485 DoFormatMessage(error); 486 HeapFree(GetProcessHeap(), 0, udpTable); 487 return FALSE; 488 } 489 490 /* Dump the UDP table */ 491 for (i = 0; i < udpTable->dwNumEntries; i++) 492 { 493 /* I've split this up so it's easier to follow */ 494 GetIpHostName(TRUE, udpTable->table[i].dwLocalAddr, HostIp, sizeof(HostIp)); 495 GetPortName(udpTable->table[i].dwLocalPort, "udp", HostPort, sizeof(HostPort)); 496 497 sprintf(Host, "%s:%s", HostIp, HostPort); 498 499 if (bDoShowProcessId) 500 { 501 sprintf(PID, "%ld", udpTable->table[i].dwOwningPid); 502 } 503 else 504 { 505 PID[0] = 0; 506 } 507 508 ConPrintf(StdOut, L" %-6s %-22S %-34s %S\n", L"UDP", Host, L"*:*", PID); 509 } 510 511 HeapFree(GetProcessHeap(), 0, udpTable); 512 return TRUE; 513 } 514 515 /* 516 * Translate port numbers into their text equivalent if there is one 517 */ 518 PCHAR 519 GetPortName(UINT Port, PCSTR Proto, CHAR Name[], INT NameLen) 520 { 521 struct servent *pServent; 522 523 if (bDoShowNumbers) 524 { 525 sprintf(Name, "%d", htons((WORD)Port)); 526 return Name; 527 } 528 /* Try to translate to a name */ 529 if ((pServent = getservbyport(Port, Proto))) 530 strcpy(Name, pServent->s_name); 531 else 532 sprintf(Name, "%d", htons((WORD)Port)); 533 return Name; 534 } 535 536 /* 537 * convert addresses into dotted decimal or hostname 538 */ 539 PCHAR 540 GetIpHostName(BOOL Local, UINT IpAddr, CHAR Name[], INT NameLen) 541 { 542 // struct hostent *phostent; 543 UINT nIpAddr; 544 545 /* display dotted decimal */ 546 nIpAddr = htonl(IpAddr); 547 if (bDoShowNumbers) { 548 sprintf(Name, "%d.%d.%d.%d", 549 (nIpAddr >> 24) & 0xFF, 550 (nIpAddr >> 16) & 0xFF, 551 (nIpAddr >> 8) & 0xFF, 552 (nIpAddr) & 0xFF); 553 return Name; 554 } 555 556 Name[0] = '\0'; 557 558 /* try to resolve the name */ 559 if (!IpAddr) { 560 if (!Local) { 561 sprintf(Name, "%d.%d.%d.%d", 562 (nIpAddr >> 24) & 0xFF, 563 (nIpAddr >> 16) & 0xFF, 564 (nIpAddr >> 8) & 0xFF, 565 (nIpAddr) & 0xFF); 566 } else { 567 if (gethostname(Name, NameLen) != 0) 568 DoFormatMessage(WSAGetLastError()); 569 } 570 } else if (IpAddr == 0x0100007f) { 571 if (Local) { 572 if (gethostname(Name, NameLen) != 0) 573 DoFormatMessage(WSAGetLastError()); 574 } else { 575 strncpy(Name, "localhost", 10); 576 } 577 // } else if (phostent = gethostbyaddr((char*)&ipaddr, sizeof(nipaddr), PF_INET)) { 578 // strcpy(name, phostent->h_name); 579 } else { 580 sprintf(Name, "%d.%d.%d.%d", 581 ((nIpAddr >> 24) & 0x000000FF), 582 ((nIpAddr >> 16) & 0x000000FF), 583 ((nIpAddr >> 8) & 0x000000FF), 584 ((nIpAddr) & 0x000000FF)); 585 } 586 return Name; 587 } 588 589 /* 590 * Parse command line parameters and set any options 591 * Run display output, looping over set interval if a number is given 592 */ 593 int wmain(int argc, wchar_t *argv[]) 594 { 595 BOOL Success; 596 WSADATA wsaData; 597 598 /* Initialize the Console Standard Streams */ 599 ConInitStdStreams(); 600 601 if (!ParseCmdline(argc, argv)) 602 return EXIT_FAILURE; 603 604 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) 605 { 606 ConResPrintf(StdErr, IDS_ERROR_WSA_START, WSAGetLastError()); 607 return EXIT_FAILURE; 608 } 609 610 Success = DisplayOutput(); 611 while (bLoopOutput && Success) 612 { 613 Sleep(Interval*1000); 614 Success = DisplayOutput(); 615 } 616 617 WSACleanup(); 618 return (Success ? EXIT_SUCCESS : EXIT_FAILURE); 619 } 620