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