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